Migrate from using ast::Module to Program

Enforce all places where Dawn passes in or returns a ast::Module, now takes a `const Program* ` or returns a `Program`.

As the end goal of all this is to have immutable Programs, all Program inputs take a pointer instead of moving the actual object.

As consumers of a Program are now all const, we have to const_cast to work around all the places we've been incorrectly mutating a ast::Module.
These const_casts are temporary, and will be fixed in the next set of changes.

Depends on https://dawn-review.googlesource.com/c/dawn/+/38522

Bug: tint:390
Change-Id: Ie05b112b16134937d1b601e9b713ea4ec4e1c677
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/38541
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index 156cb69..20d18ba 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -373,6 +373,7 @@
     "src/inspector/scalar.h",
     "src/namer.cc",
     "src/namer.h",
+    "src/program.cc",
     "src/program.h",
     "src/reader/reader.cc",
     "src/reader/reader.h",
@@ -791,7 +792,6 @@
     "src/ast/loop_statement_test.cc",
     "src/ast/member_accessor_expression_test.cc",
     "src/ast/module_clone_test.cc",
-    "src/ast/module_test.cc",
     "src/ast/null_literal_test.cc",
     "src/ast/return_statement_test.cc",
     "src/ast/scalar_constructor_expression_test.cc",
@@ -817,6 +817,7 @@
     "src/diagnostic/printer_test.cc",
     "src/inspector/inspector_test.cc",
     "src/namer_test.cc",
+    "src/program_test.cc",
     "src/scope_stack_test.cc",
     "src/symbol_table_test.cc",
     "src/symbol_test.cc",
diff --git a/fuzzers/tint_ast_clone_fuzzer.cc b/fuzzers/tint_ast_clone_fuzzer.cc
index 6a898f1..6c339e9 100644
--- a/fuzzers/tint_ast_clone_fuzzer.cc
+++ b/fuzzers/tint_ast_clone_fuzzer.cc
@@ -47,15 +47,15 @@
 
   tint::Source::File file("test.wgsl", str);
 
-  // Parse the wgsl, create the src module
+  // Parse the wgsl, create the src program
   tint::reader::wgsl::ParserImpl parser(&file);
   parser.set_max_errors(1);
   if (!parser.Parse()) {
     return 0;
   }
-  auto src = parser.module();
+  auto src = parser.program();
 
-  // Clone the src module to dst
+  // Clone the src program to dst
   auto dst = src.Clone();
 
   // Expect the demangled AST printed with to_str() to match
@@ -78,24 +78,25 @@
     ASSERT_EQ(src_types.count(dst_type.second), 0u);
   }
 
-  // Regenerate the wgsl for the src module. We use this instead of the original
-  // source so that reformatting doesn't impact the final wgsl comparision.
-  // Note that the src module is moved into the generator and this generator has
-  // a limited scope, so that the src module is released before we attempt to
-  // print the dst module.
-  // This guarantee that all the source module nodes and types are destructed
-  // and freed.
-  // ASAN should error if there's any remaining references in dst when we try to
-  // reconstruct the WGSL.
+  // Regenerate the wgsl for the src program. We use this instead of the
+  // original source so that reformatting doesn't impact the final wgsl
+  // comparison.
   std::string src_wgsl;
   {
-    tint::writer::wgsl::Generator src_gen(std::move(src));
+    tint::writer::wgsl::Generator src_gen(&src);
     ASSERT_TRUE(src_gen.Generate());
     src_wgsl = src_gen.result();
+
+    // Move the src program to a temporary that'll be dropped, so that the src
+    // program is released before we attempt to print the dst program. This
+    // guarantee that all the source program nodes and types are destructed and
+    // freed. ASAN should error if there's any remaining references in dst when
+    // we try to reconstruct the WGSL.
+    auto tmp = std::move(src);
   }
 
-  // Print the dst module, check it matches the original source
-  tint::writer::wgsl::Generator dst_gen(std::move(dst));
+  // Print the dst program, check it matches the original source
+  tint::writer::wgsl::Generator dst_gen(&dst);
   ASSERT_TRUE(dst_gen.Generate());
   auto dst_wgsl = dst_gen.result();
   ASSERT_EQ(src_wgsl, dst_wgsl);
diff --git a/fuzzers/tint_common_fuzzer.cc b/fuzzers/tint_common_fuzzer.cc
index 66826a7..4c83b6a 100644
--- a/fuzzers/tint_common_fuzzer.cc
+++ b/fuzzers/tint_common_fuzzer.cc
@@ -76,23 +76,23 @@
     return 0;
   }
 
-  auto mod = parser->module();
-  if (!mod.IsValid()) {
+  auto program = parser->program();
+  if (!program.IsValid()) {
     return 0;
   }
 
-  TypeDeterminer td(&mod);
+  TypeDeterminer td(&program);
   if (!td.Determine()) {
     return 0;
   }
 
   Validator v;
-  if (!v.Validate(&mod)) {
+  if (!v.Validate(&program)) {
     return 0;
   }
 
   if (inspector_enabled_) {
-    inspector::Inspector inspector(mod);
+    inspector::Inspector inspector(&program);
 
     auto entry_points = inspector.GetEntryPoints();
     if (inspector.has_error()) {
@@ -154,12 +154,12 @@
   }
 
   if (transform_manager_) {
-    auto out = transform_manager_->Run(&mod);
+    auto out = transform_manager_->Run(&program);
     if (out.diagnostics.contains_errors()) {
       return 0;
     }
 
-    mod = std::move(out.module);
+    program = std::move(out.program);
   }
 
   std::unique_ptr<writer::Writer> writer;
@@ -167,22 +167,22 @@
   switch (output_) {
     case OutputFormat::kWGSL:
 #if TINT_BUILD_WGSL_WRITER
-      writer = std::make_unique<writer::wgsl::Generator>(std::move(mod));
+      writer = std::make_unique<writer::wgsl::Generator>(&program);
 #endif  // TINT_BUILD_WGSL_WRITER
       break;
     case OutputFormat::kSpv:
 #if TINT_BUILD_SPV_WRITER
-      writer = std::make_unique<writer::spirv::Generator>(std::move(mod));
+      writer = std::make_unique<writer::spirv::Generator>(&program);
 #endif  // TINT_BUILD_SPV_WRITER
       break;
     case OutputFormat::kHLSL:
 #if TINT_BUILD_HLSL_WRITER
-      writer = std::make_unique<writer::hlsl::Generator>(std::move(mod));
+      writer = std::make_unique<writer::hlsl::Generator>(&program);
 #endif  // TINT_BUILD_HLSL_WRITER
       break;
     case OutputFormat::kMSL:
 #if TINT_BUILD_MSL_WRITER
-      writer = std::make_unique<writer::msl::Generator>(std::move(mod));
+      writer = std::make_unique<writer::msl::Generator>(&program);
 #endif  // TINT_BUILD_MSL_WRITER
       break;
     case OutputFormat::kNone:
diff --git a/samples/main.cc b/samples/main.cc
index 678d3d3..b429369 100644
--- a/samples/main.cc
+++ b/samples/main.cc
@@ -496,22 +496,22 @@
     diag_formatter.format(reader->diagnostics(), diag_printer.get());
     return 1;
   }
-  auto mod = reader->module();
-  if (!mod.IsValid()) {
-    std::cerr << "Invalid module generated..." << std::endl;
+  auto program = reader->program();
+  if (!program.IsValid()) {
+    std::cerr << "Invalid program generated..." << std::endl;
     return 1;
   }
 
-  tint::TypeDeterminer td(&mod);
+  tint::TypeDeterminer td(&program);
   if (!td.Determine()) {
     std::cerr << "Type Determination: " << td.error() << std::endl;
     return 1;
   }
 
   if (options.dump_ast) {
-    auto ast_str = mod.to_str();
+    auto ast_str = program.to_str();
     if (options.demangle) {
-      ast_str = tint::Demangler().Demangle(mod, ast_str);
+      ast_str = tint::Demangler().Demangle(program, ast_str);
     }
     std::cout << std::endl << ast_str << std::endl;
   }
@@ -520,7 +520,7 @@
   }
 
   tint::Validator v;
-  if (!v.Validate(&mod)) {
+  if (!v.Validate(&program)) {
     diag_formatter.format(v.diagnostics(), diag_printer.get());
     return 1;
   }
@@ -546,37 +546,40 @@
     }
   }
 
-  auto out = transform_manager.Run(&mod);
+  auto out = transform_manager.Run(&program);
   if (out.diagnostics.contains_errors()) {
     diag_formatter.format(out.diagnostics, diag_printer.get());
     return 1;
   }
 
-  mod = std::move(out.module);
+  program = std::move(out.program);
 
   std::unique_ptr<tint::writer::Writer> writer;
 
 #if TINT_BUILD_SPV_WRITER
   if (options.format == Format::kSpirv || options.format == Format::kSpvAsm) {
-    writer = std::make_unique<tint::writer::spirv::Generator>(std::move(mod));
+    writer =
+        std::make_unique<tint::writer::spirv::Generator>(&program);
   }
 #endif  // TINT_BUILD_SPV_WRITER
 
 #if TINT_BUILD_WGSL_WRITER
   if (options.format == Format::kWgsl) {
-    writer = std::make_unique<tint::writer::wgsl::Generator>(std::move(mod));
+    writer =
+        std::make_unique<tint::writer::wgsl::Generator>(&program);
   }
 #endif  // TINT_BUILD_WGSL_WRITER
 
 #if TINT_BUILD_MSL_WRITER
   if (options.format == Format::kMsl) {
-    writer = std::make_unique<tint::writer::msl::Generator>(std::move(mod));
+    writer = std::make_unique<tint::writer::msl::Generator>(&program);
   }
 #endif  // TINT_BUILD_MSL_WRITER
 
 #if TINT_BUILD_HLSL_WRITER
   if (options.format == Format::kHlsl) {
-    writer = std::make_unique<tint::writer::hlsl::Generator>(std::move(mod));
+    writer =
+        std::make_unique<tint::writer::hlsl::Generator>(&program);
   }
 #endif  // TINT_BUILD_HLSL_WRITER
 
@@ -641,7 +644,7 @@
     auto* w = static_cast<tint::writer::Text*>(writer.get());
     auto output = w->result();
     if (options.demangle) {
-      output = tint::Demangler().Demangle(mod, output);
+      output = tint::Demangler().Demangle(program, output);
     }
     if (!WriteFile(options.output_file, "w", output)) {
       return 1;
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index cb0edaf..638f26a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -187,6 +187,7 @@
   inspector/scalar.h
   namer.cc
   namer.h
+  program.cc
   program.h
   reader/reader.cc
   reader/reader.h
@@ -421,7 +422,6 @@
     ast/loop_statement_test.cc
     ast/member_accessor_expression_test.cc
     ast/module_clone_test.cc
-    ast/module_test.cc
     ast/null_literal_test.cc
     ast/return_statement_test.cc
     ast/scalar_constructor_expression_test.cc
@@ -447,6 +447,7 @@
     diagnostic/printer_test.cc
     inspector/inspector_test.cc
     namer_test.cc
+    program_test.cc
     scope_stack_test.cc
     symbol_table_test.cc
     symbol_test.cc
diff --git a/src/ast/access_decoration.cc b/src/ast/access_decoration.cc
index 51e2b73..996c3c7 100644
--- a/src/ast/access_decoration.cc
+++ b/src/ast/access_decoration.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/access_decoration.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::AccessDecoration);
 
diff --git a/src/ast/array_accessor_expression.cc b/src/ast/array_accessor_expression.cc
index ad5b1ee..6a9e6be 100644
--- a/src/ast/array_accessor_expression.cc
+++ b/src/ast/array_accessor_expression.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/array_accessor_expression.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::ArrayAccessorExpression);
 
diff --git a/src/ast/assignment_statement.cc b/src/ast/assignment_statement.cc
index 02b7c2b..a0b1a2b 100644
--- a/src/ast/assignment_statement.cc
+++ b/src/ast/assignment_statement.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/assignment_statement.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::AssignmentStatement);
 
diff --git a/src/ast/binary_expression.cc b/src/ast/binary_expression.cc
index e9970f8..de5065d 100644
--- a/src/ast/binary_expression.cc
+++ b/src/ast/binary_expression.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/binary_expression.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::BinaryExpression);
 
diff --git a/src/ast/binding_decoration.cc b/src/ast/binding_decoration.cc
index 9f686a2..05a0d86 100644
--- a/src/ast/binding_decoration.cc
+++ b/src/ast/binding_decoration.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/binding_decoration.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::BindingDecoration);
 
diff --git a/src/ast/bitcast_expression.cc b/src/ast/bitcast_expression.cc
index 39fc72f..85c42a5 100644
--- a/src/ast/bitcast_expression.cc
+++ b/src/ast/bitcast_expression.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/bitcast_expression.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::BitcastExpression);
 
diff --git a/src/ast/block_statement.cc b/src/ast/block_statement.cc
index dfbf12f..2ce6b34 100644
--- a/src/ast/block_statement.cc
+++ b/src/ast/block_statement.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/block_statement.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::BlockStatement);
 
diff --git a/src/ast/bool_literal.cc b/src/ast/bool_literal.cc
index d7c5346..a8004e6 100644
--- a/src/ast/bool_literal.cc
+++ b/src/ast/bool_literal.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/bool_literal.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::BoolLiteral);
 
diff --git a/src/ast/break_statement.cc b/src/ast/break_statement.cc
index 4115174..1a7cc9d 100644
--- a/src/ast/break_statement.cc
+++ b/src/ast/break_statement.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/break_statement.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::BreakStatement);
 
diff --git a/src/ast/builder.cc b/src/ast/builder.cc
index b46ee0e..d929a02 100644
--- a/src/ast/builder.cc
+++ b/src/ast/builder.cc
@@ -17,15 +17,15 @@
 namespace tint {
 namespace ast {
 
-TypesBuilder::TypesBuilder(Module* mod)
-    : bool_(mod->create<type::Bool>()),
-      f32(mod->create<type::F32>()),
-      i32(mod->create<type::I32>()),
-      u32(mod->create<type::U32>()),
-      void_(mod->create<type::Void>()),
-      mod_(mod) {}
+TypesBuilder::TypesBuilder(Program* p)
+    : bool_(p->create<type::Bool>()),
+      f32(p->create<type::F32>()),
+      i32(p->create<type::I32>()),
+      u32(p->create<type::U32>()),
+      void_(p->create<type::Void>()),
+      program_(p) {}
 
-Builder::Builder(Module* m) : mod(m), ty(m) {}
+Builder::Builder(Program* p) : program(p), ty(p), mod(p) {}
 
 Builder::~Builder() = default;
 
@@ -40,8 +40,8 @@
                        type::Type* type,
                        Expression* constructor,
                        VariableDecorationList decorations) {
-  auto* var = create<Variable>(mod->RegisterSymbol(name), storage, type, false,
-                               constructor, decorations);
+  auto* var = create<Variable>(program->RegisterSymbol(name), storage, type,
+                               false, constructor, decorations);
   OnVariableBuilt(var);
   return var;
 }
@@ -52,8 +52,8 @@
                        type::Type* type,
                        Expression* constructor,
                        VariableDecorationList decorations) {
-  auto* var = create<Variable>(source, mod->RegisterSymbol(name), storage, type,
-                               false, constructor, decorations);
+  auto* var = create<Variable>(source, program->RegisterSymbol(name), storage,
+                               type, false, constructor, decorations);
   OnVariableBuilt(var);
   return var;
 }
@@ -69,8 +69,8 @@
                          type::Type* type,
                          Expression* constructor,
                          VariableDecorationList decorations) {
-  auto* var = create<Variable>(mod->RegisterSymbol(name), storage, type, true,
-                               constructor, decorations);
+  auto* var = create<Variable>(program->RegisterSymbol(name), storage, type,
+                               true, constructor, decorations);
   OnVariableBuilt(var);
   return var;
 }
@@ -81,16 +81,16 @@
                          type::Type* type,
                          Expression* constructor,
                          VariableDecorationList decorations) {
-  auto* var = create<Variable>(source, mod->RegisterSymbol(name), storage, type,
-                               true, constructor, decorations);
+  auto* var = create<Variable>(source, program->RegisterSymbol(name), storage,
+                               type, true, constructor, decorations);
   OnVariableBuilt(var);
   return var;
 }
 
-BuilderWithModule::BuilderWithModule() : Builder(new Module()) {}
+BuilderWithProgram::BuilderWithProgram() : Builder(new Program()) {}
 
-BuilderWithModule::~BuilderWithModule() {
-  delete mod;
+BuilderWithProgram::~BuilderWithProgram() {
+  delete program;
 }
 
 }  // namespace ast
diff --git a/src/ast/builder.h b/src/ast/builder.h
index 35a49e1..62462ac 100644
--- a/src/ast/builder.h
+++ b/src/ast/builder.h
@@ -27,7 +27,6 @@
 #include "src/ast/float_literal.h"
 #include "src/ast/identifier_expression.h"
 #include "src/ast/member_accessor_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/scalar_constructor_expression.h"
 #include "src/ast/sint_literal.h"
 #include "src/ast/struct.h"
@@ -36,6 +35,7 @@
 #include "src/ast/type_constructor_expression.h"
 #include "src/ast/uint_literal.h"
 #include "src/ast/variable.h"
+#include "src/program.h"
 #include "src/type/alias_type.h"
 #include "src/type/array_type.h"
 #include "src/type/bool_type.h"
@@ -56,8 +56,8 @@
 class TypesBuilder {
  public:
   /// Constructor
-  /// @param mod the module
-  explicit TypesBuilder(Module* mod);
+  /// @param program the program
+  explicit TypesBuilder(Program* program);
 
   /// A boolean type
   type::Bool* const bool_;
@@ -79,80 +79,80 @@
   /// @return the tint AST type for a 2-element vector of the C type `T`.
   template <typename T>
   type::Vector* vec2() const {
-    return mod_->create<type::Vector>(Of<T>(), 2);
+    return program_->create<type::Vector>(Of<T>(), 2);
   }
 
   /// @return the tint AST type for a 3-element vector of the C type `T`.
   template <typename T>
   type::Vector* vec3() const {
-    return mod_->create<type::Vector>(Of<T>(), 3);
+    return program_->create<type::Vector>(Of<T>(), 3);
   }
 
   /// @return the tint AST type for a 4-element vector of the C type `T`.
   template <typename T>
   type::Type* vec4() const {
-    return mod_->create<type::Vector>(Of<T>(), 4);
+    return program_->create<type::Vector>(Of<T>(), 4);
   }
 
   /// @return the tint AST type for a 2x3 matrix of the C type `T`.
   template <typename T>
   type::Matrix* mat2x2() const {
-    return mod_->create<type::Matrix>(Of<T>(), 2, 2);
+    return program_->create<type::Matrix>(Of<T>(), 2, 2);
   }
 
   /// @return the tint AST type for a 2x3 matrix of the C type `T`.
   template <typename T>
   type::Matrix* mat2x3() const {
-    return mod_->create<type::Matrix>(Of<T>(), 3, 2);
+    return program_->create<type::Matrix>(Of<T>(), 3, 2);
   }
 
   /// @return the tint AST type for a 2x4 matrix of the C type `T`.
   template <typename T>
   type::Matrix* mat2x4() const {
-    return mod_->create<type::Matrix>(Of<T>(), 4, 2);
+    return program_->create<type::Matrix>(Of<T>(), 4, 2);
   }
 
   /// @return the tint AST type for a 3x2 matrix of the C type `T`.
   template <typename T>
   type::Matrix* mat3x2() const {
-    return mod_->create<type::Matrix>(Of<T>(), 2, 3);
+    return program_->create<type::Matrix>(Of<T>(), 2, 3);
   }
 
   /// @return the tint AST type for a 3x3 matrix of the C type `T`.
   template <typename T>
   type::Matrix* mat3x3() const {
-    return mod_->create<type::Matrix>(Of<T>(), 3, 3);
+    return program_->create<type::Matrix>(Of<T>(), 3, 3);
   }
 
   /// @return the tint AST type for a 3x4 matrix of the C type `T`.
   template <typename T>
   type::Matrix* mat3x4() const {
-    return mod_->create<type::Matrix>(Of<T>(), 4, 3);
+    return program_->create<type::Matrix>(Of<T>(), 4, 3);
   }
 
   /// @return the tint AST type for a 4x2 matrix of the C type `T`.
   template <typename T>
   type::Matrix* mat4x2() const {
-    return mod_->create<type::Matrix>(Of<T>(), 2, 4);
+    return program_->create<type::Matrix>(Of<T>(), 2, 4);
   }
 
   /// @return the tint AST type for a 4x3 matrix of the C type `T`.
   template <typename T>
   type::Matrix* mat4x3() const {
-    return mod_->create<type::Matrix>(Of<T>(), 3, 4);
+    return program_->create<type::Matrix>(Of<T>(), 3, 4);
   }
 
   /// @return the tint AST type for a 4x4 matrix of the C type `T`.
   template <typename T>
   type::Matrix* mat4x4() const {
-    return mod_->create<type::Matrix>(Of<T>(), 4, 4);
+    return program_->create<type::Matrix>(Of<T>(), 4, 4);
   }
 
   /// @param subtype the array element type
   /// @param n the array size. 0 represents a runtime-array.
   /// @return the tint AST type for a array of size `n` of type `T`
   type::Array* array(type::Type* subtype, uint32_t n) const {
-    return mod_->create<type::Array>(subtype, n, ArrayDecorationList{});
+    return program_->create<type::Array>(subtype, n, ArrayDecorationList{});
   }
 
   /// @return the tint AST type for an array of size `N` of type `T`
@@ -166,21 +166,21 @@
   /// @param type the alias type
   /// @returns the alias pointer
   type::Alias* alias(const std::string& name, type::Type* type) const {
-    return mod_->create<type::Alias>(mod_->RegisterSymbol(name), type);
+    return program_->create<type::Alias>(program_->RegisterSymbol(name), type);
   }
 
   /// @return the tint AST pointer to type `T` with the given StorageClass.
   /// @param storage_class the storage class of the pointer
   template <typename T>
   type::Pointer* pointer(StorageClass storage_class) const {
-    return mod_->create<type::Pointer>(Of<T>(), storage_class);
+    return program_->create<type::Pointer>(Of<T>(), storage_class);
   }
 
   /// @param name the struct name
   /// @param impl the struct implementation
   /// @returns a struct pointer
   type::Struct* struct_(const std::string& name, ast::Struct* impl) const {
-    return mod_->create<type::Struct>(mod_->RegisterSymbol(name), impl);
+    return program_->create<type::Struct>(program_->RegisterSymbol(name), impl);
   }
 
  private:
@@ -192,7 +192,7 @@
   template <typename T>
   struct CToAST {};
 
-  Module* const mod_;
+  Program* const program_;
 };
 
 /// Helper for building common AST constructs.
@@ -216,8 +216,8 @@
   using f32 = float;
 
   /// Constructor
-  /// @param mod the module to use in the builder
-  explicit Builder(Module* mod);
+  /// @param program the program to build
+  explicit Builder(Program* program);
   virtual ~Builder();
 
   /// @param expr the expression
@@ -227,20 +227,20 @@
   /// @param name the identifier name
   /// @return an IdentifierExpression with the given name
   IdentifierExpression* Expr(const std::string& name) {
-    return create<IdentifierExpression>(mod->RegisterSymbol(name));
+    return create<IdentifierExpression>(program->RegisterSymbol(name));
   }
 
   /// @param source the source information
   /// @param name the identifier name
   /// @return an IdentifierExpression with the given name
   IdentifierExpression* Expr(const Source& source, const std::string& name) {
-    return create<IdentifierExpression>(source, mod->RegisterSymbol(name));
+    return create<IdentifierExpression>(source, program->RegisterSymbol(name));
   }
 
   /// @param name the identifier name
   /// @return an IdentifierExpression with the given name
   IdentifierExpression* Expr(const char* name) {
-    return create<IdentifierExpression>(mod->RegisterSymbol(name));
+    return create<IdentifierExpression>(program->RegisterSymbol(name));
   }
 
   /// @param value the boolean value
@@ -602,7 +602,7 @@
   /// @param val the offset value
   /// @returns the offset decoration pointer
   StructMemberOffsetDecoration* MemberOffset(uint32_t val) {
-    return mod->create<StructMemberOffsetDecoration>(source_, val);
+    return program->create<StructMemberOffsetDecoration>(source_, val);
   }
 
   /// Creates a Function
@@ -619,9 +619,9 @@
                  type::Type* type,
                  ast::StatementList body,
                  ast::FunctionDecorationList decorations) {
-    return mod->create<ast::Function>(source, mod->RegisterSymbol(name), params,
-                                      type, create<ast::BlockStatement>(body),
-                                      decorations);
+    return program->create<ast::Function>(
+        source, program->RegisterSymbol(name), params, type,
+        create<ast::BlockStatement>(body), decorations);
   }
 
   /// Creates a Function
@@ -636,7 +636,7 @@
                  type::Type* type,
                  ast::StatementList body,
                  ast::FunctionDecorationList decorations) {
-    return create<ast::Function>(mod->RegisterSymbol(name), params, type,
+    return create<ast::Function>(program->RegisterSymbol(name), params, type,
                                  create<ast::BlockStatement>(body),
                                  decorations);
   }
@@ -649,8 +649,8 @@
   StructMember* Member(const Source& source,
                        const std::string& name,
                        type::Type* type) {
-    return mod->create<StructMember>(source, mod->RegisterSymbol(name), type,
-                                     StructMemberDecorationList{});
+    return program->create<StructMember>(source, program->RegisterSymbol(name),
+                                         type, StructMemberDecorationList{});
   }
 
   /// Creates a StructMember
@@ -658,8 +658,8 @@
   /// @param type the struct member type
   /// @returns the struct member pointer
   StructMember* Member(const std::string& name, type::Type* type) {
-    return mod->create<StructMember>(source_, mod->RegisterSymbol(name), type,
-                                     StructMemberDecorationList{});
+    return program->create<StructMember>(source_, program->RegisterSymbol(name),
+                                         type, StructMemberDecorationList{});
   }
 
   /// Creates a StructMember
@@ -670,8 +670,8 @@
   StructMember* Member(const std::string& name,
                        type::Type* type,
                        StructMemberDecorationList decos) {
-    return mod->create<StructMember>(source_, mod->RegisterSymbol(name), type,
-                                     decos);
+    return program->create<StructMember>(source_, program->RegisterSymbol(name),
+                                         type, decos);
   }
 
   /// Creates a new Node owned by the Module, with the explicit Source.
@@ -682,7 +682,7 @@
   template <typename T, typename... ARGS>
   traits::EnableIfIsType<T, Node>* create(const Source& source,
                                           ARGS&&... args) {
-    return mod->create<T>(source, std::forward<ARGS>(args)...);
+    return program->create<T>(source, std::forward<ARGS>(args)...);
   }
 
   /// Creates a new Node owned by the Module, with the explicit Source.
@@ -692,7 +692,7 @@
   /// @returns the node pointer
   template <typename T, typename... ARGS>
   traits::EnableIfIsType<T, Node>* create(Source&& source, ARGS&&... args) {
-    return mod->create<T>(std::move(source), std::forward<ARGS>(args)...);
+    return program->create<T>(std::move(source), std::forward<ARGS>(args)...);
   }
 
   /// Creates a new type::Type owned by the Module, using the Builder's
@@ -702,7 +702,7 @@
   /// @returns the node pointer
   template <typename T, typename... ARGS>
   traits::EnableIfIsType<T, Node>* create(ARGS&&... args) {
-    return mod->create<T>(source_, std::forward<ARGS>(args)...);
+    return program->create<T>(source_, std::forward<ARGS>(args)...);
   }
 
   /// Creates a new type::Type owned by the Module.
@@ -720,7 +720,7 @@
   traits::EnableIfIsType<T, type::Type>* create(ARGS&&... args) {
     static_assert(std::is_base_of<type::Type, T>::value,
                   "T does not derive from type::Type");
-    return mod->create<T>(std::forward<ARGS>(args)...);
+    return program->create<T>(std::forward<ARGS>(args)...);
   }
 
   /// Sets the current builder source to `src`
@@ -731,11 +731,14 @@
   /// @param loc the Source used for future create() calls
   void SetSource(const Source::Location& loc) { source_ = Source(loc); }
 
-  /// The builder module
-  Module* const mod;
+  /// The builder program
+  Program* const program;
   /// The builder types
   const TypesBuilder ty;
 
+  /// [DEPRECATED] Temporary alias to #program
+  Program* const mod;
+
  protected:
   /// Called whenever a new variable is built with `Var()`.
   virtual void OnVariableBuilt(Variable*) {}
@@ -744,11 +747,11 @@
   Source source_;
 };
 
-/// BuilderWithModule is a `Builder` that constructs and owns its `Module`.
-class BuilderWithModule : public Builder {
+/// BuilderWithProgram is a `Builder` that constructs and owns its `Program`.
+class BuilderWithProgram : public Builder {
  public:
-  BuilderWithModule();
-  ~BuilderWithModule() override;
+  BuilderWithProgram();
+  ~BuilderWithProgram() override;
 };
 
 //! @cond Doxygen_Suppress
diff --git a/src/ast/builtin_decoration.cc b/src/ast/builtin_decoration.cc
index 0cfd811..d0db918 100644
--- a/src/ast/builtin_decoration.cc
+++ b/src/ast/builtin_decoration.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/builtin_decoration.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::BuiltinDecoration);
 
diff --git a/src/ast/call_expression.cc b/src/ast/call_expression.cc
index 6144b4d..61e5316 100644
--- a/src/ast/call_expression.cc
+++ b/src/ast/call_expression.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/call_expression.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::CallExpression);
 
diff --git a/src/ast/call_statement.cc b/src/ast/call_statement.cc
index f70f36b..82eedc8 100644
--- a/src/ast/call_statement.cc
+++ b/src/ast/call_statement.cc
@@ -15,8 +15,8 @@
 #include "src/ast/call_statement.h"
 
 #include "src/ast/call_expression.h"
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::CallStatement);
 
diff --git a/src/ast/case_statement.cc b/src/ast/case_statement.cc
index 62cae3f..84e6b21 100644
--- a/src/ast/case_statement.cc
+++ b/src/ast/case_statement.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/case_statement.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::CaseStatement);
 
diff --git a/src/ast/constant_id_decoration.cc b/src/ast/constant_id_decoration.cc
index c97c84d..c2bb255 100644
--- a/src/ast/constant_id_decoration.cc
+++ b/src/ast/constant_id_decoration.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/constant_id_decoration.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::ConstantIdDecoration);
 
diff --git a/src/ast/continue_statement.cc b/src/ast/continue_statement.cc
index d380a83..98557bc 100644
--- a/src/ast/continue_statement.cc
+++ b/src/ast/continue_statement.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/continue_statement.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::ContinueStatement);
 
diff --git a/src/ast/discard_statement.cc b/src/ast/discard_statement.cc
index a8f0d3c..1a522cc 100644
--- a/src/ast/discard_statement.cc
+++ b/src/ast/discard_statement.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/discard_statement.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::DiscardStatement);
 
diff --git a/src/ast/else_statement.cc b/src/ast/else_statement.cc
index a9d5cf1..67c52f2 100644
--- a/src/ast/else_statement.cc
+++ b/src/ast/else_statement.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/else_statement.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::ElseStatement);
 
diff --git a/src/ast/fallthrough_statement.cc b/src/ast/fallthrough_statement.cc
index 378c5fc..f18ea60 100644
--- a/src/ast/fallthrough_statement.cc
+++ b/src/ast/fallthrough_statement.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/fallthrough_statement.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::FallthroughStatement);
 
diff --git a/src/ast/float_literal.cc b/src/ast/float_literal.cc
index 8795e0f..734706f 100644
--- a/src/ast/float_literal.cc
+++ b/src/ast/float_literal.cc
@@ -17,8 +17,8 @@
 #include <limits>
 #include <sstream>
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::FloatLiteral);
 
diff --git a/src/ast/function.cc b/src/ast/function.cc
index 96fd6d2..9123896 100644
--- a/src/ast/function.cc
+++ b/src/ast/function.cc
@@ -16,11 +16,11 @@
 
 #include <sstream>
 
-#include "src/ast/module.h"
 #include "src/ast/stage_decoration.h"
 #include "src/ast/variable.h"
 #include "src/ast/workgroup_decoration.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 #include "src/type/multisampled_texture_type.h"
 #include "src/type/sampled_texture_type.h"
 #include "src/type/texture_type.h"
diff --git a/src/ast/group_decoration.cc b/src/ast/group_decoration.cc
index 599493e..738882c 100644
--- a/src/ast/group_decoration.cc
+++ b/src/ast/group_decoration.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/group_decoration.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::GroupDecoration);
 
diff --git a/src/ast/identifier_expression.cc b/src/ast/identifier_expression.cc
index 05c771f..e10c664 100644
--- a/src/ast/identifier_expression.cc
+++ b/src/ast/identifier_expression.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/identifier_expression.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::IdentifierExpression);
 
diff --git a/src/ast/if_statement.cc b/src/ast/if_statement.cc
index 80171b1..e7e0609 100644
--- a/src/ast/if_statement.cc
+++ b/src/ast/if_statement.cc
@@ -15,8 +15,8 @@
 #include "src/ast/if_statement.h"
 
 #include "src/ast/else_statement.h"
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::IfStatement);
 
diff --git a/src/ast/location_decoration.cc b/src/ast/location_decoration.cc
index 8202dfe..7b23c2a 100644
--- a/src/ast/location_decoration.cc
+++ b/src/ast/location_decoration.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/location_decoration.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::LocationDecoration);
 
diff --git a/src/ast/loop_statement.cc b/src/ast/loop_statement.cc
index 14fb504..cee9f23 100644
--- a/src/ast/loop_statement.cc
+++ b/src/ast/loop_statement.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/loop_statement.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::LoopStatement);
 
diff --git a/src/ast/member_accessor_expression.cc b/src/ast/member_accessor_expression.cc
index 4cbb2db..d25c6e8 100644
--- a/src/ast/member_accessor_expression.cc
+++ b/src/ast/member_accessor_expression.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/member_accessor_expression.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::MemberAccessorExpression);
 
diff --git a/src/ast/module.cc b/src/ast/module.cc
index 39bd5e4..0de64bb 100644
--- a/src/ast/module.cc
+++ b/src/ast/module.cc
@@ -14,117 +14,10 @@
 
 #include "src/ast/module.h"
 
-#include <sstream>
-
-#include "src/clone_context.h"
-#include "src/type/struct_type.h"
-
 namespace tint {
 namespace ast {
 
-Module::Module() = default;
-
-Module::Module(Module&&) = default;
-
-Module& Module::operator=(Module&& rhs) = default;
-
-Module::~Module() = default;
-
-Module Module::Clone() const {
-  Module out;
-  CloneContext(&out, this).Clone();
-  return out;
-}
-
-void Module::Clone(CloneContext* ctx) const {
-  for (auto* ty : constructed_types_) {
-    ctx->dst->constructed_types_.emplace_back(ctx->Clone(ty));
-  }
-  for (auto* var : global_variables_) {
-    ctx->dst->global_variables_.emplace_back(ctx->Clone(var));
-  }
-  for (auto* func : functions_) {
-    ctx->dst->functions_.emplace_back(ctx->Clone(func));
-  }
-}
-
-Symbol Module::RegisterSymbol(const std::string& name) {
-  return symbol_table_.Register(name);
-}
-
-Symbol Module::GetSymbol(const std::string& name) const {
-  return symbol_table_.GetSymbol(name);
-}
-
-std::string Module::SymbolToName(const Symbol sym) const {
-  return symbol_table_.NameFor(sym);
-}
-
-bool Module::IsValid() const {
-  for (auto* var : global_variables_) {
-    if (var == nullptr || !var->IsValid()) {
-      return false;
-    }
-  }
-  for (auto* const ty : constructed_types_) {
-    if (ty == nullptr) {
-      return false;
-    }
-    if (auto* alias = ty->As<type::Alias>()) {
-      if (alias->type() == nullptr) {
-        return false;
-      }
-      if (auto* str = alias->type()->As<type::Struct>()) {
-        if (!str->symbol().IsValid()) {
-          return false;
-        }
-      }
-    } else if (auto* str = ty->As<type::Struct>()) {
-      if (!str->symbol().IsValid()) {
-        return false;
-      }
-    } else {
-      return false;
-    }
-  }
-  for (auto* func : functions_) {
-    if (func == nullptr || !func->IsValid()) {
-      return false;
-    }
-  }
-  return true;
-}
-
-std::string Module::to_str() const {
-  std::ostringstream out;
-
-  out << "Module{" << std::endl;
-  const auto indent = 2;
-  for (auto* const ty : constructed_types_) {
-    for (size_t i = 0; i < indent; ++i) {
-      out << " ";
-    }
-    if (auto* alias = ty->As<type::Alias>()) {
-      out << alias->symbol().to_str() << " -> " << alias->type()->type_name()
-          << std::endl;
-      if (auto* str = alias->type()->As<type::Struct>()) {
-        str->impl()->to_str(out, indent);
-      }
-    } else if (auto* str = ty->As<type::Struct>()) {
-      out << str->symbol().to_str() << " ";
-      str->impl()->to_str(out, indent);
-    }
-  }
-  for (auto* var : global_variables_) {
-    var->to_str(out, indent);
-  }
-  for (auto* func : functions_) {
-    func->to_str(out, indent);
-  }
-  out << "}" << std::endl;
-
-  return out.str();
-}
+// Placeholder
 
 }  // namespace ast
 }  // namespace tint
diff --git a/src/ast/module.h b/src/ast/module.h
index 393f3db..3e2beeb 100644
--- a/src/ast/module.h
+++ b/src/ast/module.h
@@ -15,149 +15,10 @@
 #ifndef SRC_AST_MODULE_H_
 #define SRC_AST_MODULE_H_
 
-#include <functional>
-#include <memory>
-#include <string>
-#include <type_traits>
-#include <unordered_map>
-#include <utility>
-#include <vector>
-
-#include "src/ast/function.h"
-#include "src/ast/variable.h"
-#include "src/block_allocator.h"
-#include "src/symbol_table.h"
-#include "src/traits.h"
-#include "src/type/alias_type.h"
-#include "src/type/type_manager.h"
-
 namespace tint {
 namespace ast {
 
-/// Represents all the source in a given program.
-class Module {
- public:
-  /// Constructor
-  Module();
-
-  /// Move constructor
-  Module(Module&&);
-
-  /// Move assignment operator
-  /// @param rhs the Module to move
-  /// @return this Module
-  Module& operator=(Module&& rhs);
-
-  /// Destructor
-  ~Module();
-
-  /// @return a deep copy of this module
-  Module Clone() const;
-
-  /// Clone this module into `ctx->mod` using the provided CloneContext
-  /// The module will be cloned in this order:
-  /// * Constructed types
-  /// * Global variables
-  /// * Functions
-  /// @param ctx the clone context
-  void Clone(CloneContext* ctx) const;
-
-  /// Add a global variable to the module
-  /// @param var the variable to add
-  void AddGlobalVariable(Variable* var) { global_variables_.push_back(var); }
-  /// @returns the global variables for the module
-  const VariableList& global_variables() const { return global_variables_; }
-
-  /// @returns the global variables for the module
-  VariableList& global_variables() { return global_variables_; }
-
-  /// Adds a constructed type to the module.
-  /// The type must be an alias or a struct.
-  /// @param type the constructed type to add
-  void AddConstructedType(type::Type* type) {
-    constructed_types_.push_back(type);
-  }
-  /// @returns the constructed types in the module
-  const std::vector<type::Type*>& constructed_types() const {
-    return constructed_types_;
-  }
-
-  /// @returns the functions declared in the translation unit
-  const FunctionList& Functions() const { return functions_; }
-
-  /// @returns the functions declared in the translation unit
-  FunctionList& Functions() { return functions_; }
-
-  /// @returns true if all required fields in the AST are present.
-  bool IsValid() const;
-
-  /// @returns a string representation of the module
-  std::string to_str() const;
-
-  /// Creates a new Node owned by the Module. When the Module is
-  /// destructed, the Node will also be destructed.
-  /// @param args the arguments to pass to the type constructor
-  /// @returns the node pointer
-  template <typename T, typename... ARGS>
-  traits::EnableIfIsType<T, Node>* create(ARGS&&... args) {
-    return ast_nodes_.Create<T>(std::forward<ARGS>(args)...);
-  }
-
-  /// Creates a new type::Type owned by the Module.
-  /// When the Module is destructed, owned Module and the returned
-  /// `Type` will also be destructed.
-  /// Types are unique (de-aliased), and so calling create() for the same `T`
-  /// and arguments will return the same pointer.
-  /// @warning Use this method to acquire a type only if all of its type
-  /// information is provided in the constructor arguments `args`.<br>
-  /// If the type requires additional configuration after construction that
-  /// affect its fundamental type, build the type with `std::make_unique`, make
-  /// any necessary alterations and then call unique_type() instead.
-  /// @param args the arguments to pass to the type constructor
-  /// @returns the de-aliased type pointer
-  template <typename T, typename... ARGS>
-  traits::EnableIfIsType<T, type::Type>* create(ARGS&&... args) {
-    static_assert(std::is_base_of<type::Type, T>::value,
-                  "T does not derive from type::Type");
-    return type_mgr_.Get<T>(std::forward<ARGS>(args)...);
-  }
-
-  /// Returns all the declared types in the module
-  /// @returns the mapping from name string to type.
-  const std::unordered_map<std::string, type::Type*>& types() {
-    return type_mgr_.types();
-  }
-
-  /// @returns all the declared nodes in the module
-  BlockAllocator<Node>::View nodes() { return ast_nodes_.Objects(); }
-
-  /// Registers `name` as a symbol
-  /// @param name the name to register
-  /// @returns the symbol for the `name`. If `name` is already registered the
-  /// previously generated symbol will be returned.
-  Symbol RegisterSymbol(const std::string& name);
-
-  /// Returns the symbol for `name`
-  /// @param name the name to lookup
-  /// @returns the symbol for name or symbol::kInvalid
-  Symbol GetSymbol(const std::string& name) const;
-
-  /// Returns the `name` for `sym`
-  /// @param sym the symbol to retrieve the name for
-  /// @returns the use provided `name` for the symbol or "" if not found
-  std::string SymbolToName(const Symbol sym) const;
-
- private:
-  Module(const Module&) = delete;
-
-  SymbolTable symbol_table_;
-  VariableList global_variables_;
-  // The constructed types are owned by the type manager
-  std::vector<type::Type*> constructed_types_;
-  FunctionList functions_;
-  BlockAllocator<Node> ast_nodes_;
-  type::Manager type_mgr_;
-};
+// Placeholder
 
 }  // namespace ast
 }  // namespace tint
diff --git a/src/ast/module_clone_test.cc b/src/ast/module_clone_test.cc
index f855fcb..b32c577 100644
--- a/src/ast/module_clone_test.cc
+++ b/src/ast/module_clone_test.cc
@@ -108,12 +108,12 @@
 
 )");
 
-  // Parse the wgsl, create the src module
+  // Parse the wgsl, create the src program
   reader::wgsl::Parser parser(&file);
   ASSERT_TRUE(parser.Parse()) << parser.error();
-  auto src = parser.module();
+  auto src = parser.program();
 
-  // Clone the src module to dst
+  // Clone the src program to dst
   auto dst = src.Clone();
 
   // Expect the AST printed with to_str() to match
@@ -138,24 +138,25 @@
         << dst_type.second->type_name();
   }
 
-  // Regenerate the wgsl for the src module. We use this instead of the original
-  // source so that reformatting doesn't impact the final wgsl comparision.
-  // Note that the src module is moved into the generator and this generator has
-  // a limited scope, so that the src module is released before we attempt to
-  // print the dst module.
-  // This guarantee that all the source module nodes and types are destructed
-  // and freed.
-  // ASAN should error if there's any remaining references in dst when we try to
-  // reconstruct the WGSL.
+  // Regenerate the wgsl for the src program. We use this instead of the
+  // original source so that reformatting doesn't impact the final wgsl
+  // comparison.
   std::string src_wgsl;
   {
-    writer::wgsl::Generator src_gen(std::move(src));
-    ASSERT_TRUE(src_gen.Generate()) << src_gen.error();
+    tint::writer::wgsl::Generator src_gen(&src);
+    ASSERT_TRUE(src_gen.Generate());
     src_wgsl = src_gen.result();
+
+    // Move the src program to a temporary that'll be dropped, so that the src
+    // program is released before we attempt to print the dst program. This
+    // guarantee that all the source program nodes and types are destructed and
+    // freed. ASAN should error if there's any remaining references in dst when
+    // we try to reconstruct the WGSL.
+    auto tmp = std::move(src);
   }
 
-  // Print the dst module, check it matches the original source
-  writer::wgsl::Generator dst_gen(std::move(dst));
+  // Print the dst program, check it matches the original source
+  tint::writer::wgsl::Generator dst_gen(&dst);
   ASSERT_TRUE(dst_gen.Generate());
   auto dst_wgsl = dst_gen.result();
   ASSERT_EQ(src_wgsl, dst_wgsl);
diff --git a/src/ast/node.h b/src/ast/node.h
index 924ffd1..1c215e4 100644
--- a/src/ast/node.h
+++ b/src/ast/node.h
@@ -32,8 +32,6 @@
 
 namespace ast {
 
-class Module;
-
 /// AST base class node
 class Node : public Castable<Node> {
  public:
diff --git a/src/ast/null_literal.cc b/src/ast/null_literal.cc
index 1bb8cc1..7a52a7f 100644
--- a/src/ast/null_literal.cc
+++ b/src/ast/null_literal.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/null_literal.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::NullLiteral);
 
diff --git a/src/ast/return_statement.cc b/src/ast/return_statement.cc
index 105e7e5..8602460 100644
--- a/src/ast/return_statement.cc
+++ b/src/ast/return_statement.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/return_statement.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::ReturnStatement);
 
diff --git a/src/ast/scalar_constructor_expression.cc b/src/ast/scalar_constructor_expression.cc
index 4658081..dfa4ae3 100644
--- a/src/ast/scalar_constructor_expression.cc
+++ b/src/ast/scalar_constructor_expression.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/scalar_constructor_expression.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::ScalarConstructorExpression);
 
diff --git a/src/ast/sint_literal.cc b/src/ast/sint_literal.cc
index e5a2210..4957286 100644
--- a/src/ast/sint_literal.cc
+++ b/src/ast/sint_literal.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/sint_literal.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::SintLiteral);
 
diff --git a/src/ast/stage_decoration.cc b/src/ast/stage_decoration.cc
index 4867d7b..e359ac4 100644
--- a/src/ast/stage_decoration.cc
+++ b/src/ast/stage_decoration.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/stage_decoration.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::StageDecoration);
 
diff --git a/src/ast/stride_decoration.cc b/src/ast/stride_decoration.cc
index 16d7a14..1473d02 100644
--- a/src/ast/stride_decoration.cc
+++ b/src/ast/stride_decoration.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/stride_decoration.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::StrideDecoration);
 
diff --git a/src/ast/struct.cc b/src/ast/struct.cc
index 1302d8d..92e01f7 100644
--- a/src/ast/struct.cc
+++ b/src/ast/struct.cc
@@ -14,9 +14,9 @@
 
 #include "src/ast/struct.h"
 
-#include "src/ast/module.h"
 #include "src/ast/struct_block_decoration.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::Struct);
 
diff --git a/src/ast/struct_block_decoration.cc b/src/ast/struct_block_decoration.cc
index c12902c..55af859 100644
--- a/src/ast/struct_block_decoration.cc
+++ b/src/ast/struct_block_decoration.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/struct_block_decoration.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::StructBlockDecoration);
 
diff --git a/src/ast/struct_member.cc b/src/ast/struct_member.cc
index 28fbd3a..4ecd79d 100644
--- a/src/ast/struct_member.cc
+++ b/src/ast/struct_member.cc
@@ -14,9 +14,9 @@
 
 #include "src/ast/struct_member.h"
 
-#include "src/ast/module.h"
 #include "src/ast/struct_member_offset_decoration.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::StructMember);
 
diff --git a/src/ast/struct_member_offset_decoration.cc b/src/ast/struct_member_offset_decoration.cc
index 380d480..71fbfc9 100644
--- a/src/ast/struct_member_offset_decoration.cc
+++ b/src/ast/struct_member_offset_decoration.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/struct_member_offset_decoration.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::StructMemberOffsetDecoration);
 
diff --git a/src/ast/switch_statement.cc b/src/ast/switch_statement.cc
index cbd2018..3e536cd 100644
--- a/src/ast/switch_statement.cc
+++ b/src/ast/switch_statement.cc
@@ -15,8 +15,8 @@
 #include "src/ast/switch_statement.h"
 
 #include "src/ast/case_statement.h"
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::SwitchStatement);
 
diff --git a/src/ast/test_helper.h b/src/ast/test_helper.h
index 7cb44f8..ab6d468 100644
--- a/src/ast/test_helper.h
+++ b/src/ast/test_helper.h
@@ -21,15 +21,15 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/builder.h"
-#include "src/ast/module.h"
 #include "src/demangler.h"
+#include "src/program.h"
 
 namespace tint {
 namespace ast {
 
 /// Helper class for testing
 template <typename BASE>
-class TestHelperBase : public BASE, public BuilderWithModule {
+class TestHelperBase : public BASE, public BuilderWithProgram {
  public:
   /// Demangles the given string
   /// @param s the string to demangle
diff --git a/src/ast/type_constructor_expression.cc b/src/ast/type_constructor_expression.cc
index e8dbcc4..b5807b4 100644
--- a/src/ast/type_constructor_expression.cc
+++ b/src/ast/type_constructor_expression.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/type_constructor_expression.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::TypeConstructorExpression);
 
diff --git a/src/ast/uint_literal.cc b/src/ast/uint_literal.cc
index be00e75..00d414b 100644
--- a/src/ast/uint_literal.cc
+++ b/src/ast/uint_literal.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/uint_literal.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::UintLiteral);
 
diff --git a/src/ast/unary_op_expression.cc b/src/ast/unary_op_expression.cc
index 100a376..21c6a05 100644
--- a/src/ast/unary_op_expression.cc
+++ b/src/ast/unary_op_expression.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/unary_op_expression.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::UnaryOpExpression);
 
diff --git a/src/ast/variable.cc b/src/ast/variable.cc
index 1e579e1..0e4c336 100644
--- a/src/ast/variable.cc
+++ b/src/ast/variable.cc
@@ -17,8 +17,8 @@
 #include <assert.h>
 
 #include "src/ast/constant_id_decoration.h"
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::Variable);
 
diff --git a/src/ast/variable_decl_statement.cc b/src/ast/variable_decl_statement.cc
index d915dd0..91a56d1 100644
--- a/src/ast/variable_decl_statement.cc
+++ b/src/ast/variable_decl_statement.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/variable_decl_statement.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::VariableDeclStatement);
 
diff --git a/src/ast/workgroup_decoration.cc b/src/ast/workgroup_decoration.cc
index b6e6702..57ea5e4 100644
--- a/src/ast/workgroup_decoration.cc
+++ b/src/ast/workgroup_decoration.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/workgroup_decoration.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::ast::WorkgroupDecoration);
 
diff --git a/src/clone_context.cc b/src/clone_context.cc
index 1eb8833..5eb1a86 100644
--- a/src/clone_context.cc
+++ b/src/clone_context.cc
@@ -14,11 +14,11 @@
 
 #include "src/clone_context.h"
 
-#include "src/ast/module.h"
+#include "src/program.h"
 
 namespace tint {
 
-CloneContext::CloneContext(ast::Module* to, ast::Module const* from)
+CloneContext::CloneContext(Program* to, Program const* from)
     : dst(to), src(from) {}
 CloneContext::~CloneContext() = default;
 
diff --git a/src/clone_context.h b/src/clone_context.h
index 9a0cd55..1f742b9 100644
--- a/src/clone_context.h
+++ b/src/clone_context.h
@@ -27,29 +27,27 @@
 namespace tint {
 
 // Forward declarations
-namespace ast {
-class Module;
-}  // namespace ast
+class Program;
 
 /// CloneContext holds the state used while cloning AST nodes and types.
 class CloneContext {
  public:
   /// Constructor
-  /// @param to the target module to clone into
-  /// @param from the source module to clone from
-  CloneContext(ast::Module* to, ast::Module const* from);
+  /// @param to the target program to clone into
+  /// @param from the source program to clone from
+  CloneContext(Program* to, Program const* from);
 
   /// Destructor
   ~CloneContext();
 
-  /// Clones the Node or type::Type `a` into the module #dst if `a` is not
+  /// Clones the Node or type::Type `a` into the program #dst if `a` is not
   /// null. If `a` is null, then Clone() returns null. If `a` has been cloned
   /// already by this CloneContext then the same cloned pointer is returned.
   ///
   /// Clone() may use a function registered with ReplaceAll() to create a
   /// transformed version of the object. See ReplaceAll() for more information.
   ///
-  /// The Node or type::Type `a` must be owned by the module #src.
+  /// The Node or type::Type `a` must be owned by the program #src.
   ///
   /// @note Semantic information such as resolved expression type and intrinsic
   /// information is not cloned.
@@ -78,7 +76,7 @@
 
   /// Clones the Source `s` into `dst`
   /// TODO(bclayton) - Currently this 'clone' is a shallow copy. If/when
-  /// `Source.File`s are owned by the `Module` this should make a copy of the
+  /// `Source.File`s are owned by the Program this should make a copy of the
   /// file.
   /// @param s the `Source` to clone
   /// @return the cloned source
@@ -86,15 +84,15 @@
 
   /// Clones the Symbol `s` into `dst`
   ///
-  /// The Symbol `s` must be owned by the module #src.
+  /// The Symbol `s` must be owned by the program #src.
   ///
   /// @param s the Symbol to clone
   /// @return the cloned source
   Symbol Clone(const Symbol& s) const;
 
-  /// Clones each of the elements of the vector `v` into the module #dst->
+  /// Clones each of the elements of the vector `v` into the program #dst.
   ///
-  /// All the elements of the vector `v` must be owned by the module #src.
+  /// All the elements of the vector `v` must be owned by the program #src.
   ///
   /// @param v the vector to clone
   /// @return the cloned vector
@@ -147,14 +145,14 @@
     return *this;
   }
 
-  /// Clone performs the clone of the entire module #src to #dst.
+  /// Clone performs the clone of the entire program #src to #dst.
   void Clone();
 
-  /// The target module to clone into.
-  ast::Module* const dst;
+  /// The target program to clone into.
+  Program* const dst;
 
-  /// The source module to clone from.
-  ast::Module const* const src;
+  /// The source program to clone from.
+  Program const* const src;
 
  private:
   using Transform = std::function<CastableBase*(CastableBase*)>;
diff --git a/src/clone_context_test.cc b/src/clone_context_test.cc
index a0f378f..5762cf3 100644
--- a/src/clone_context_test.cc
+++ b/src/clone_context_test.cc
@@ -16,7 +16,7 @@
 
 #include "gtest/gtest.h"
 
-#include "src/ast/module.h"
+#include "src/program.h"
 
 namespace tint {
 namespace {
@@ -44,7 +44,7 @@
 struct Replacement : public Castable<Replacement, Replaceable> {};
 
 TEST(CloneContext, Clone) {
-  ast::Module original;
+  Program original;
   auto* original_root = original.create<Cloneable>();
   original_root->a = original.create<Cloneable>();
   original_root->a->b = original.create<Cloneable>();
@@ -63,7 +63,7 @@
   //
   // C: Clonable
 
-  ast::Module cloned;
+  Program cloned;
   auto* cloned_root = CloneContext(&cloned, &original).Clone(original_root);
 
   EXPECT_NE(cloned_root->a, nullptr);
@@ -88,7 +88,7 @@
 }
 
 TEST(CloneContext, CloneWithReplacements) {
-  ast::Module original;
+  Program original;
   auto* original_root = original.create<Cloneable>();
   original_root->a = original.create<Cloneable>();
   original_root->a->b = original.create<Replaceable>();
@@ -107,7 +107,7 @@
   // C: Clonable
   // R: Replaceable
 
-  ast::Module cloned;
+  Program cloned;
   auto* cloned_root = CloneContext(&cloned, &original)
                           .ReplaceAll([&](CloneContext* ctx, Replaceable* in) {
                             auto* out = cloned.create<Replacement>();
diff --git a/src/demangler.cc b/src/demangler.cc
index c874d26..9296d11 100644
--- a/src/demangler.cc
+++ b/src/demangler.cc
@@ -26,7 +26,7 @@
 
 Demangler::~Demangler() = default;
 
-std::string Demangler::Demangle(const ast::Module& mod,
+std::string Demangler::Demangle(const Program& program,
                                 const std::string& str) const {
   auto ret = str;
 
@@ -46,7 +46,7 @@
     auto id = ret.substr(start_idx, len);
 
     Symbol sym(std::stoi(id));
-    auto name = mod.SymbolToName(sym);
+    auto name = program.SymbolToName(sym);
     ret.replace(idx, end_idx - idx, name);
 
     pos = idx + name.length();
diff --git a/src/demangler.h b/src/demangler.h
index 23f9a2e..9496d6c 100644
--- a/src/demangler.h
+++ b/src/demangler.h
@@ -17,7 +17,7 @@
 
 #include <string>
 
-#include "src/ast/module.h"
+#include "src/program.h"
 
 namespace tint {
 
@@ -30,10 +30,10 @@
   ~Demangler();
 
   /// Transforms given string and replaces any symbols with original names
-  /// @param mod the module where the symbols are registered
+  /// @param program the program where the symbols are registered
   /// @param str the string to replace
   /// @returns the string with any symbol replacements performed.
-  std::string Demangle(const ast::Module& mod, const std::string& str) const;
+  std::string Demangle(const Program& program, const std::string& str) const;
 };
 
 }  // namespace tint
diff --git a/src/demangler_test.cc b/src/demangler_test.cc
index cc0477c..9e83fb4 100644
--- a/src/demangler_test.cc
+++ b/src/demangler_test.cc
@@ -15,6 +15,7 @@
 #include "src/demangler.h"
 
 #include "gtest/gtest.h"
+#include "src/program.h"
 
 namespace tint {
 namespace {
@@ -22,7 +23,7 @@
 using DemanglerTest = testing::Test;
 
 TEST_F(DemanglerTest, NoSymbols) {
-  ast::Module m;
+  Program m;
   m.RegisterSymbol("sym1");
 
   Demangler d;
@@ -30,7 +31,7 @@
 }
 
 TEST_F(DemanglerTest, Symbol) {
-  ast::Module m;
+  Program m;
   m.RegisterSymbol("sym1");
 
   Demangler d;
@@ -38,7 +39,7 @@
 }
 
 TEST_F(DemanglerTest, MultipleSymbols) {
-  ast::Module m;
+  Program m;
   m.RegisterSymbol("sym1");
   m.RegisterSymbol("sym2");
 
diff --git a/src/inspector/inspector.cc b/src/inspector/inspector.cc
index ab60122..97c02cc 100644
--- a/src/inspector/inspector.cc
+++ b/src/inspector/inspector.cc
@@ -43,29 +43,27 @@
 namespace tint {
 namespace inspector {
 
-Inspector::Inspector(const ast::Module& module) : module_(module) {}
-
-Inspector::Inspector(const Program* program) : Inspector(program->module) {}
+Inspector::Inspector(const Program* program) : program_(*program) {}
 
 Inspector::~Inspector() = default;
 
 std::vector<EntryPoint> Inspector::GetEntryPoints() {
   std::vector<EntryPoint> result;
 
-  for (auto* func : module_.Functions()) {
+  for (auto* func : program_.Functions()) {
     if (!func->IsEntryPoint()) {
       continue;
     }
 
     EntryPoint entry_point;
-    entry_point.name = module_.SymbolToName(func->symbol());
-    entry_point.remapped_name = module_.SymbolToName(func->symbol());
+    entry_point.name = program_.SymbolToName(func->symbol());
+    entry_point.remapped_name = program_.SymbolToName(func->symbol());
     entry_point.stage = func->pipeline_stage();
     std::tie(entry_point.workgroup_size_x, entry_point.workgroup_size_y,
              entry_point.workgroup_size_z) = func->workgroup_size();
 
     for (auto* var : func->referenced_module_variables()) {
-      auto name = module_.SymbolToName(var->symbol());
+      auto name = program_.SymbolToName(var->symbol());
       if (var->HasBuiltinDecoration()) {
         continue;
       }
@@ -108,7 +106,7 @@
 
 std::map<uint32_t, Scalar> Inspector::GetConstantIDs() {
   std::map<uint32_t, Scalar> result;
-  for (auto* var : module_.global_variables()) {
+  for (auto* var : program_.global_variables()) {
     if (!var->HasConstantIdDecoration()) {
       continue;
     }
@@ -285,7 +283,7 @@
 }
 
 ast::Function* Inspector::FindEntryPointByName(const std::string& name) {
-  auto* func = module_.Functions().Find(module_.GetSymbol(name));
+  auto* func = program_.Functions().Find(program_.GetSymbol(name));
   if (!func) {
     error_ += name + " was not found!";
     return nullptr;
diff --git a/src/inspector/inspector.h b/src/inspector/inspector.h
index 662726c..5ba70be 100644
--- a/src/inspector/inspector.h
+++ b/src/inspector/inspector.h
@@ -21,7 +21,6 @@
 #include <tuple>
 #include <vector>
 
-#include "src/ast/module.h"
 #include "src/ast/pipeline_stage.h"
 #include "src/inspector/entry_point.h"
 #include "src/inspector/scalar.h"
@@ -68,14 +67,10 @@
   SampledKind sampled_kind;
 };
 
-/// Extracts information from a module
+/// Extracts information from a program
 class Inspector {
  public:
   /// Constructor
-  /// @param module Shader module to extract information from.
-  explicit Inspector(const ast::Module& module);
-
-  /// Constructor
   /// @param program Shader program to extract information from.
   explicit Inspector(const Program* program);
 
@@ -134,7 +129,7 @@
       const std::string& entry_point);
 
  private:
-  const ast::Module& module_;
+  const Program& program_;
   std::string error_;
 
   /// @param name name of the entry point to find
diff --git a/src/inspector/inspector_test.cc b/src/inspector/inspector_test.cc
index 9067461..b214dc9 100644
--- a/src/inspector/inspector_test.cc
+++ b/src/inspector/inspector_test.cc
@@ -67,11 +67,11 @@
 namespace inspector {
 namespace {
 
-class InspectorHelper : public ast::BuilderWithModule {
+class InspectorHelper : public ast::BuilderWithProgram {
  public:
   InspectorHelper()
       : td_(std::make_unique<TypeDeterminer>(mod)),
-        inspector_(std::make_unique<Inspector>(*mod)),
+        inspector_(std::make_unique<Inspector>(mod)),
         sampler_type_(type::SamplerKind::kSampler),
         comparison_sampler_type_(type::SamplerKind::kComparisonSampler) {}
 
@@ -317,7 +317,7 @@
     return {struct_type, std::move(access_type)};
   }
 
-  /// Adds a binding variable with a struct type to the module
+  /// Adds a binding variable with a struct type to the program
   /// @param name the name of the variable
   /// @param type the type to use
   /// @param storage_class the storage class to use
@@ -337,7 +337,7 @@
     mod->AddGlobalVariable(var);
   }
 
-  /// Adds an uniform buffer variable to the module
+  /// Adds an uniform buffer variable to the program
   /// @param name the name of the variable
   /// @param type the type to use
   /// @param group the binding/group/ to use for the uniform buffer
@@ -349,7 +349,7 @@
     AddBinding(name, type, ast::StorageClass::kUniform, group, binding);
   }
 
-  /// Adds a storage buffer variable to the module
+  /// Adds a storage buffer variable to the program
   /// @param name the name of the variable
   /// @param type the type to use
   /// @param group the binding/group to use for the storage buffer
@@ -398,7 +398,7 @@
                 ast::FunctionDecorationList{});
   }
 
-  /// Adds a regular sampler variable to the module
+  /// Adds a regular sampler variable to the program
   /// @param name the name of the variable
   /// @param group the binding/group to use for the storage buffer
   /// @param binding the binding number to use for the storage buffer
@@ -407,7 +407,7 @@
                binding);
   }
 
-  /// Adds a comparison sampler variable to the module
+  /// Adds a comparison sampler variable to the program
   /// @param name the name of the variable
   /// @param group the binding/group to use for the storage buffer
   /// @param binding the binding number to use for the storage buffer
@@ -444,7 +444,7 @@
     return create<type::MultisampledTexture>(dim, type);
   }
 
-  /// Adds a sampled texture variable to the module
+  /// Adds a sampled texture variable to the program
   /// @param name the name of the variable
   /// @param type the type to use
   /// @param group the binding/group to use for the sampled texture
@@ -456,7 +456,7 @@
     AddBinding(name, type, ast::StorageClass::kUniformConstant, group, binding);
   }
 
-  /// Adds a multi-sampled texture variable to the module
+  /// Adds a multi-sampled texture variable to the program
   /// @param name the name of the variable
   /// @param type the type to use
   /// @param group the binding/group to use for the multi-sampled texture
@@ -473,7 +473,7 @@
         Var(name, ast::StorageClass::kUniformConstant, type));
   }
 
-  /// Adds a depth texture variable to the module
+  /// Adds a depth texture variable to the program
   /// @param name the name of the variable
   /// @param type the type to use
   void AddDepthTexture(const std::string& name, type::Type* type) {
diff --git a/src/namer.cc b/src/namer.cc
index f5f5600..405a56a 100644
--- a/src/namer.cc
+++ b/src/namer.cc
@@ -22,7 +22,7 @@
 
 namespace tint {
 
-Namer::Namer(ast::Module* mod) : module_(mod) {}
+Namer::Namer(Program* program) : program_(program) {}
 
 Namer::~Namer() = default;
 
@@ -42,7 +42,7 @@
   return name;
 }
 
-MangleNamer::MangleNamer(ast::Module* mod) : Namer(mod) {}
+MangleNamer::MangleNamer(Program* program) : Namer(program) {}
 
 MangleNamer::~MangleNamer() = default;
 
@@ -50,12 +50,12 @@
   return sym.to_str();
 }
 
-UnsafeNamer::UnsafeNamer(ast::Module* mod) : Namer(mod) {}
+UnsafeNamer::UnsafeNamer(Program* program) : Namer(program) {}
 
 UnsafeNamer::~UnsafeNamer() = default;
 
 std::string UnsafeNamer::NameFor(const Symbol& sym) {
-  return module_->SymbolToName(sym);
+  return program_->SymbolToName(sym);
 }
 
 }  // namespace tint
diff --git a/src/namer.h b/src/namer.h
index 8d05eb2..c818c3f 100644
--- a/src/namer.h
+++ b/src/namer.h
@@ -19,7 +19,7 @@
 #include <unordered_map>
 #include <unordered_set>
 
-#include "src/ast/module.h"
+#include "src/program.h"
 
 namespace tint {
 
@@ -27,8 +27,8 @@
 class Namer {
  public:
   /// Constructor
-  /// @param mod the module this namer works with
-  explicit Namer(ast::Module* mod);
+  /// @param program the program this namer works with
+  explicit Namer(Program* program);
   /// Destructor
   virtual ~Namer();
 
@@ -48,8 +48,8 @@
   /// @returns true if `name` has already been used
   bool IsUsed(const std::string& name);
 
-  /// The module storing the symbol table
-  ast::Module* module_ = nullptr;
+  /// The program storing the symbol table
+  Program* program_ = nullptr;
 
  private:
   // The list of names taken by the remapper
@@ -60,8 +60,8 @@
 class MangleNamer : public Namer {
  public:
   /// Constructor
-  /// @param mod the module to retrieve names from
-  explicit MangleNamer(ast::Module* mod);
+  /// @param program the program to retrieve names from
+  explicit MangleNamer(Program* program);
   /// Destructor
   ~MangleNamer() override;
 
@@ -77,8 +77,8 @@
 class UnsafeNamer : public Namer {
  public:
   /// Constructor
-  /// @param mod the module to retrieve names from
-  explicit UnsafeNamer(ast::Module* mod);
+  /// @param program the program to retrieve names from
+  explicit UnsafeNamer(Program* program);
   /// Destructor
   ~UnsafeNamer() override;
 
diff --git a/src/namer_test.cc b/src/namer_test.cc
index 5a318f7..552a959 100644
--- a/src/namer_test.cc
+++ b/src/namer_test.cc
@@ -15,7 +15,7 @@
 #include "src/namer.h"
 
 #include "gtest/gtest.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 
 namespace tint {
 namespace {
@@ -23,7 +23,7 @@
 using NamerTest = testing::Test;
 
 TEST_F(NamerTest, GenerateName) {
-  ast::Module m;
+  Program m;
   MangleNamer n(&m);
   EXPECT_EQ("name", n.GenerateName("name"));
   EXPECT_EQ("name_0", n.GenerateName("name"));
@@ -33,7 +33,7 @@
 using MangleNamerTest = testing::Test;
 
 TEST_F(MangleNamerTest, ReturnsName) {
-  ast::Module m;
+  Program m;
   auto s = m.RegisterSymbol("my_sym");
 
   MangleNamer n(&m);
@@ -41,7 +41,7 @@
 }
 
 TEST_F(MangleNamerTest, ReturnsSameValueForSameName) {
-  ast::Module m;
+  Program m;
   auto s1 = m.RegisterSymbol("my_sym");
   auto s2 = m.RegisterSymbol("my_sym2");
 
@@ -53,7 +53,7 @@
 
 using UnsafeNamerTest = testing::Test;
 TEST_F(UnsafeNamerTest, ReturnsName) {
-  ast::Module m;
+  Program m;
   auto s = m.RegisterSymbol("my_sym");
 
   UnsafeNamer n(&m);
diff --git a/src/program.cc b/src/program.cc
new file mode 100644
index 0000000..b2abaa4
--- /dev/null
+++ b/src/program.cc
@@ -0,0 +1,128 @@
+// Copyright 2021 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/program.h"
+
+#include <sstream>
+
+#include "src/clone_context.h"
+#include "src/type/struct_type.h"
+
+namespace tint {
+
+Program::Program() = default;
+
+Program::Program(Program&&) = default;
+
+Program& Program::operator=(Program&& rhs) = default;
+
+Program::~Program() = default;
+
+Program Program::Clone() const {
+  Program out;
+  CloneContext(&out, this).Clone();
+  return out;
+}
+
+void Program::Clone(CloneContext* ctx) const {
+  for (auto* ty : constructed_types_) {
+    ctx->dst->constructed_types_.emplace_back(ctx->Clone(ty));
+  }
+  for (auto* var : global_variables_) {
+    ctx->dst->global_variables_.emplace_back(ctx->Clone(var));
+  }
+  for (auto* func : functions_) {
+    ctx->dst->functions_.emplace_back(ctx->Clone(func));
+  }
+}
+
+Symbol Program::RegisterSymbol(const std::string& name) {
+  return symbol_table_.Register(name);
+}
+
+Symbol Program::GetSymbol(const std::string& name) const {
+  return symbol_table_.GetSymbol(name);
+}
+
+std::string Program::SymbolToName(const Symbol sym) const {
+  return symbol_table_.NameFor(sym);
+}
+
+bool Program::IsValid() const {
+  for (auto* var : global_variables_) {
+    if (var == nullptr || !var->IsValid()) {
+      return false;
+    }
+  }
+  for (auto* const ty : constructed_types_) {
+    if (ty == nullptr) {
+      return false;
+    }
+    if (auto* alias = ty->As<type::Alias>()) {
+      if (alias->type() == nullptr) {
+        return false;
+      }
+      if (auto* str = alias->type()->As<type::Struct>()) {
+        if (!str->symbol().IsValid()) {
+          return false;
+        }
+      }
+    } else if (auto* str = ty->As<type::Struct>()) {
+      if (!str->symbol().IsValid()) {
+        return false;
+      }
+    } else {
+      return false;
+    }
+  }
+  for (auto* func : functions_) {
+    if (func == nullptr || !func->IsValid()) {
+      return false;
+    }
+  }
+  return true;
+}
+
+std::string Program::to_str() const {
+  std::ostringstream out;
+
+  out << "Module{" << std::endl;
+  const auto indent = 2;
+  for (auto* const ty : constructed_types_) {
+    for (size_t i = 0; i < indent; ++i) {
+      out << " ";
+    }
+    if (auto* alias = ty->As<type::Alias>()) {
+      out << alias->symbol().to_str() << " -> " << alias->type()->type_name()
+          << std::endl;
+      if (auto* str = alias->type()->As<type::Struct>()) {
+        str->impl()->to_str(out, indent);
+      }
+    } else if (auto* str = ty->As<type::Struct>()) {
+      out << str->symbol().to_str() << " ";
+      str->impl()->to_str(out, indent);
+    }
+  }
+  for (auto* var : global_variables_) {
+    var->to_str(out, indent);
+  }
+  for (auto* func : functions_) {
+    func->to_str(out, indent);
+  }
+  out << "}" << std::endl;
+
+  return out.str();
+}
+
+}  // namespace tint
diff --git a/src/program.h b/src/program.h
index 31c7f03..e232c3b 100644
--- a/src/program.h
+++ b/src/program.h
@@ -15,25 +15,151 @@
 #ifndef SRC_PROGRAM_H_
 #define SRC_PROGRAM_H_
 
+#include <functional>
+#include <memory>
 #include <string>
+#include <type_traits>
+#include <unordered_map>
+#include <utility>
+#include <vector>
 
-#include "src/ast/module.h"
+#include "src/ast/function.h"
+#include "src/ast/variable.h"
+#include "src/block_allocator.h"
+#include "src/symbol_table.h"
+#include "src/traits.h"
+#include "src/type/alias_type.h"
+#include "src/type/type_manager.h"
 
 namespace tint {
 
-/// Program is (currently) a simple wrapper of to ast::Module.
-/// This wrapper is used as a stepping stone to having Dawn use tint::Program
-/// instead of tint::ast::Module.
+/// Represents all the source in a given program.
 class Program {
  public:
-  /// The wrapped module
-  ast::Module module;
+  /// Constructor
+  Program();
 
-  /// @returns true if all required fields in the module are present.
-  bool IsValid() const { return module.IsValid(); }
+  /// Move constructor
+  Program(Program&&);
+
+  /// Move assignment operator
+  /// @param rhs the Program to move
+  /// @return this Program
+  Program& operator=(Program&& rhs);
+
+  /// Destructor
+  ~Program();
 
   /// @return a deep copy of this program
-  Program Clone() const { return Program{module.Clone()}; }
+  Program Clone() const;
+
+  /// Clone this program into `ctx->mod` using the provided CloneContext
+  /// The program will be cloned in this order:
+  /// * Constructed types
+  /// * Global variables
+  /// * Functions
+  /// @param ctx the clone context
+  void Clone(CloneContext* ctx) const;
+
+  /// Add a global variable to the program
+  /// @param var the variable to add
+  void AddGlobalVariable(ast::Variable* var) {
+    global_variables_.push_back(var);
+  }
+  /// @returns the global variables for the program
+  const ast::VariableList& global_variables() const {
+    return global_variables_;
+  }
+
+  /// @returns the global variables for the program
+  ast::VariableList& global_variables() { return global_variables_; }
+
+  /// Adds a constructed type to the program.
+  /// The type must be an alias or a struct.
+  /// @param type the constructed type to add
+  void AddConstructedType(type::Type* type) {
+    constructed_types_.push_back(type);
+  }
+  /// @returns the constructed types in the program
+  const std::vector<type::Type*>& constructed_types() const {
+    return constructed_types_;
+  }
+
+  /// @returns the functions declared in the translation unit
+  const ast::FunctionList& Functions() const { return functions_; }
+
+  /// @returns the functions declared in the translation unit
+  ast::FunctionList& Functions() { return functions_; }
+
+  /// @returns true if all required fields in the AST are present.
+  bool IsValid() const;
+
+  /// @returns a string representation of the program
+  std::string to_str() const;
+
+  /// Creates a new Node owned by the Program. When the Program is
+  /// destructed, the Node will also be destructed.
+  /// @param args the arguments to pass to the type constructor
+  /// @returns the node pointer
+  template <typename T, typename... ARGS>
+  traits::EnableIfIsType<T, ast::Node>* create(ARGS&&... args) {
+    return ast_nodes_.Create<T>(std::forward<ARGS>(args)...);
+  }
+
+  /// Creates a new type::Type owned by the Program.
+  /// When the Program is destructed, owned Program and the returned
+  /// `Type` will also be destructed.
+  /// Types are unique (de-aliased), and so calling create() for the same `T`
+  /// and arguments will return the same pointer.
+  /// @warning Use this method to acquire a type only if all of its type
+  /// information is provided in the constructor arguments `args`.<br>
+  /// If the type requires additional configuration after construction that
+  /// affect its fundamental type, build the type with `std::make_unique`, make
+  /// any necessary alterations and then call unique_type() instead.
+  /// @param args the arguments to pass to the type constructor
+  /// @returns the de-aliased type pointer
+  template <typename T, typename... ARGS>
+  traits::EnableIfIsType<T, type::Type>* create(ARGS&&... args) {
+    static_assert(std::is_base_of<type::Type, T>::value,
+                  "T does not derive from type::Type");
+    return type_mgr_.Get<T>(std::forward<ARGS>(args)...);
+  }
+
+  /// Returns all the declared types in the program
+  /// @returns the mapping from name string to type.
+  const std::unordered_map<std::string, type::Type*>& types() {
+    return type_mgr_.types();
+  }
+
+  /// @returns all the declared nodes in the program
+  BlockAllocator<ast::Node>::View nodes() { return ast_nodes_.Objects(); }
+
+  /// Registers `name` as a symbol
+  /// @param name the name to register
+  /// @returns the symbol for the `name`. If `name` is already registered the
+  /// previously generated symbol will be returned.
+  Symbol RegisterSymbol(const std::string& name);
+
+  /// Returns the symbol for `name`
+  /// @param name the name to lookup
+  /// @returns the symbol for name or symbol::kInvalid
+  Symbol GetSymbol(const std::string& name) const;
+
+  /// Returns the `name` for `sym`
+  /// @param sym the symbol to retrieve the name for
+  /// @returns the use provided `name` for the symbol or "" if not found
+  std::string SymbolToName(const Symbol sym) const;
+
+ private:
+  Program(const Program&) = delete;
+
+  SymbolTable symbol_table_;
+  ast::VariableList global_variables_;
+  // The constructed types are owned by the type manager
+  std::vector<type::Type*> constructed_types_;
+  ast::FunctionList functions_;
+  BlockAllocator<ast::Node> ast_nodes_;
+  type::Manager type_mgr_;
 };
 
 }  // namespace tint
diff --git a/src/ast/module_test.cc b/src/program_test.cc
similarity index 69%
rename from src/ast/module_test.cc
rename to src/program_test.cc
index 399a442..8cc5717 100644
--- a/src/ast/module_test.cc
+++ b/src/program_test.cc
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "src/ast/module.h"
+#include "src/program.h"
 
 #include <sstream>
 #include <utility>
@@ -26,82 +26,81 @@
 #include "src/type/struct_type.h"
 
 namespace tint {
-namespace ast {
 namespace {
 
-using ModuleTest = TestHelper;
+using ProgramTest = ast::TestHelper;
 
-TEST_F(ModuleTest, Creation) {
+TEST_F(ProgramTest, Creation) {
   EXPECT_EQ(mod->Functions().size(), 0u);
 }
 
-TEST_F(ModuleTest, ToStrEmitsPreambleAndPostamble) {
+TEST_F(ProgramTest, ToStrEmitsPreambleAndPostamble) {
   const auto str = mod->to_str();
   auto* const expected = "Module{\n}\n";
   EXPECT_EQ(str, expected);
 }
 
-TEST_F(ModuleTest, IsValid_Empty) {
+TEST_F(ProgramTest, IsValid_Empty) {
   EXPECT_TRUE(mod->IsValid());
 }
 
-TEST_F(ModuleTest, IsValid_GlobalVariable) {
-  auto* var = Var("var", StorageClass::kInput, ty.f32);
+TEST_F(ProgramTest, IsValid_GlobalVariable) {
+  auto* var = Var("var", ast::StorageClass::kInput, ty.f32);
   mod->AddGlobalVariable(var);
   EXPECT_TRUE(mod->IsValid());
 }
 
-TEST_F(ModuleTest, IsValid_Null_GlobalVariable) {
+TEST_F(ProgramTest, IsValid_Null_GlobalVariable) {
   mod->AddGlobalVariable(nullptr);
   EXPECT_FALSE(mod->IsValid());
 }
 
-TEST_F(ModuleTest, IsValid_Invalid_GlobalVariable) {
-  auto* var = Var("var", StorageClass::kInput, nullptr);
+TEST_F(ProgramTest, IsValid_Invalid_GlobalVariable) {
+  auto* var = Var("var", ast::StorageClass::kInput, nullptr);
   mod->AddGlobalVariable(var);
   EXPECT_FALSE(mod->IsValid());
 }
 
-TEST_F(ModuleTest, IsValid_Alias) {
+TEST_F(ProgramTest, IsValid_Alias) {
   auto* alias = ty.alias("alias", ty.f32);
   mod->AddConstructedType(alias);
   EXPECT_TRUE(mod->IsValid());
 }
 
-TEST_F(ModuleTest, IsValid_Null_Alias) {
+TEST_F(ProgramTest, IsValid_Null_Alias) {
   mod->AddConstructedType(nullptr);
   EXPECT_FALSE(mod->IsValid());
 }
 
-TEST_F(ModuleTest, IsValid_Struct) {
+TEST_F(ProgramTest, IsValid_Struct) {
   auto* st = ty.struct_("name", {});
   auto* alias = ty.alias("name", st);
   mod->AddConstructedType(alias);
   EXPECT_TRUE(mod->IsValid());
 }
 
-TEST_F(ModuleTest, IsValid_Struct_EmptyName) {
+TEST_F(ProgramTest, IsValid_Struct_EmptyName) {
   auto* st = ty.struct_("", {});
   auto* alias = ty.alias("name", st);
   mod->AddConstructedType(alias);
   EXPECT_FALSE(mod->IsValid());
 }
 
-TEST_F(ModuleTest, IsValid_Function) {
-  auto* func = Func("main", VariableList(), ty.f32, StatementList{},
+TEST_F(ProgramTest, IsValid_Function) {
+  auto* func = Func("main", ast::VariableList(), ty.f32, ast::StatementList{},
                     ast::FunctionDecorationList{});
 
   mod->Functions().Add(func);
   EXPECT_TRUE(mod->IsValid());
 }
 
-TEST_F(ModuleTest, IsValid_Null_Function) {
+TEST_F(ProgramTest, IsValid_Null_Function) {
   mod->Functions().Add(nullptr);
   EXPECT_FALSE(mod->IsValid());
 }
 
-TEST_F(ModuleTest, IsValid_Invalid_Function) {
-  auto* func = Func("main", VariableList{}, nullptr, StatementList{},
+TEST_F(ProgramTest, IsValid_Invalid_Function) {
+  auto* func = Func("main", ast::VariableList{}, nullptr, ast::StatementList{},
                     ast::FunctionDecorationList{});
 
   mod->Functions().Add(func);
@@ -109,5 +108,4 @@
 }
 
 }  // namespace
-}  // namespace ast
 }  // namespace tint
diff --git a/src/reader/reader.h b/src/reader/reader.h
index a852dd0..008d780 100644
--- a/src/reader/reader.h
+++ b/src/reader/reader.h
@@ -18,7 +18,6 @@
 #include <string>
 #include <utility>
 
-#include "src/ast/module.h"
 #include "src/diagnostic/diagnostic.h"
 #include "src/diagnostic/formatter.h"
 #include "src/program.h"
@@ -47,11 +46,8 @@
   /// @returns the full list of diagnostic messages.
   const diag::List& diagnostics() const { return diags_; }
 
-  /// @returns the module. The module in the parser will be reset after this.
-  virtual ast::Module module() = 0;
-
-  /// @returns the program. The module in the parser will be reset after this.
-  Program program() { return Program{module()}; }
+  /// @returns the program. The program in the parser will be reset after this.
+  virtual Program program() = 0;
 
  protected:
   /// Constructor
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index 41fb4bf..251a9ec 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -632,16 +632,16 @@
   /// @param cond the switch statement condition
   explicit SwitchStatementBuilder(ast::Expression* cond) : condition(cond) {}
 
-  /// @param mod the ast Module to build into
+  /// @param program the program to build into
   /// @returns the built ast::SwitchStatement
-  ast::SwitchStatement* Build(ast::Module* mod) const override {
+  ast::SwitchStatement* Build(Program* program) const override {
     // We've listed cases in reverse order in the switch statement.
     // Reorder them to match the presentation order in WGSL.
     auto reversed_cases = cases;
     std::reverse(reversed_cases.begin(), reversed_cases.end());
 
-    return mod->create<ast::SwitchStatement>(Source{}, condition,
-                                             reversed_cases);
+    return program->create<ast::SwitchStatement>(Source{}, condition,
+                                                 reversed_cases);
   }
 
   /// Switch statement condition
@@ -658,10 +658,10 @@
   /// @param c the if-statement condition
   explicit IfStatementBuilder(ast::Expression* c) : cond(c) {}
 
-  /// @param mod the ast Module to build into
+  /// @param program the program to build into
   /// @returns the built ast::IfStatement
-  ast::IfStatement* Build(ast::Module* mod) const override {
-    return mod->create<ast::IfStatement>(Source{}, cond, body, else_stmts);
+  ast::IfStatement* Build(Program* program) const override {
+    return program->create<ast::IfStatement>(Source{}, cond, body, else_stmts);
   }
 
   /// If-statement condition
@@ -676,10 +676,10 @@
 /// @see StatementBuilder
 struct LoopStatementBuilder
     : public Castable<LoopStatementBuilder, StatementBuilder> {
-  /// @param mod the ast Module to build into
+  /// @param program the program to build into
   /// @returns the built ast::LoopStatement
-  ast::LoopStatement* Build(ast::Module* mod) const override {
-    return mod->create<ast::LoopStatement>(Source{}, body, continuing);
+  ast::LoopStatement* Build(Program* program) const override {
+    return program->create<ast::LoopStatement>(Source{}, body, continuing);
   }
 
   /// Loop-statement block body
@@ -717,7 +717,7 @@
                                  const spvtools::opt::Function& function,
                                  const EntryPointInfo* ep_info)
     : parser_impl_(*pi),
-      ast_module_(pi->get_module()),
+      program_(pi->get_program()),
       ir_context_(*(pi->ir_context())),
       def_use_mgr_(ir_context_.get_def_use_mgr()),
       constant_mgr_(ir_context_.get_constant_mgr()),
@@ -725,7 +725,7 @@
       fail_stream_(pi->fail_stream()),
       namer_(pi->namer()),
       function_(function),
-      i32_(ast_module_.create<type::I32>()),
+      i32_(program_.create<type::I32>()),
       ep_info_(ep_info) {
   PushNewStatementBlock(nullptr, 0, nullptr);
 }
@@ -749,12 +749,12 @@
 
 FunctionEmitter::StatementBlock::~StatementBlock() = default;
 
-void FunctionEmitter::StatementBlock::Finalize(ast::Module* mod) {
+void FunctionEmitter::StatementBlock::Finalize(Program* program) {
   assert(!finalized_ /* Finalize() must only be called once */);
 
   for (size_t i = 0; i < statements_.size(); i++) {
     if (auto* builder = statements_[i]->As<StatementBuilder>()) {
-      statements_[i] = builder->Build(mod);
+      statements_[i] = builder->Build(program);
     }
   }
 
@@ -786,7 +786,7 @@
   const auto& top = statements_stack_.back();
 
   auto* cond = create<ast::IdentifierExpression>(
-      Source{}, ast_module_.RegisterSymbol(guard_name));
+      Source{}, program_.RegisterSymbol(guard_name));
   auto* builder = AddStatementBuilder<IfStatementBuilder>(cond);
 
   PushNewStatementBlock(
@@ -811,7 +811,7 @@
 const ast::StatementList FunctionEmitter::ast_body() {
   assert(!statements_stack_.empty());
   auto& entry = statements_stack_[0];
-  entry.Finalize(&ast_module_);
+  entry.Finalize(&program_);
   return entry.GetStatements();
 }
 
@@ -855,14 +855,13 @@
                   << statements_stack_.size();
   }
 
-  statements_stack_[0].Finalize(&ast_module_);
+  statements_stack_[0].Finalize(&program_);
 
   auto& statements = statements_stack_[0].GetStatements();
   auto* body = create<ast::BlockStatement>(Source{}, statements);
-  ast_module_.Functions().Add(
-      create<ast::Function>(decl.source, ast_module_.RegisterSymbol(decl.name),
-                            std::move(decl.params), decl.return_type, body,
-                            std::move(decl.decorations)));
+  program_.Functions().Add(create<ast::Function>(
+      decl.source, program_.RegisterSymbol(decl.name), std::move(decl.params),
+      decl.return_type, body, std::move(decl.decorations)));
 
   // Maintain the invariant by repopulating the one and only element.
   statements_stack_.clear();
@@ -2013,7 +2012,7 @@
     return TypedExpression{
         parser_impl_.ConvertType(def_use_mgr_->GetDef(id)->type_id()),
         create<ast::IdentifierExpression>(Source{},
-                                          ast_module_.RegisterSymbol(name))};
+                                          program_.RegisterSymbol(name))};
   }
   if (singly_used_values_.count(id)) {
     auto expr = std::move(singly_used_values_[id]);
@@ -2035,7 +2034,7 @@
       auto name = namer_.Name(inst->result_id());
       return TypedExpression{parser_impl_.ConvertType(inst->type_id()),
                              create<ast::IdentifierExpression>(
-                                 Source{}, ast_module_.RegisterSymbol(name))};
+                                 Source{}, program_.RegisterSymbol(name))};
     }
     default:
       break;
@@ -2079,7 +2078,7 @@
   // Close off previous constructs.
   while (!statements_stack_.empty() &&
          (statements_stack_.back().GetEndId() == block_info.id)) {
-    statements_stack_.back().Finalize(&ast_module_);
+    statements_stack_.back().Finalize(&program_);
     statements_stack_.pop_back();
   }
   if (statements_stack_.empty()) {
@@ -2265,8 +2264,8 @@
   if (!guard_name.empty()) {
     // Declare the guard variable just before the "if", initialized to true.
     auto* guard_var =
-        create<ast::Variable>(Source{},                                // source
-                              ast_module_.RegisterSymbol(guard_name),  // symbol
+        create<ast::Variable>(Source{},                             // source
+                              program_.RegisterSymbol(guard_name),  // symbol
                               ast::StorageClass::kFunction,    // storage_class
                               parser_impl_.Bool(),             // type
                               false,                           // is_const
@@ -2673,7 +2672,7 @@
         return create<ast::AssignmentStatement>(
             Source{},
             create<ast::IdentifierExpression>(
-                Source{}, ast_module_.RegisterSymbol(flow_guard)),
+                Source{}, program_.RegisterSymbol(flow_guard)),
             MakeFalse(Source{}));
       }
 
@@ -2794,7 +2793,7 @@
     assert(!phi_var_name.empty());
     auto* var = create<ast::Variable>(
         Source{},                                       // source
-        ast_module_.RegisterSymbol(phi_var_name),       // symbol
+        program_.RegisterSymbol(phi_var_name),          // symbol
         ast::StorageClass::kFunction,                   // storage_class
         parser_impl_.ConvertType(def_inst->type_id()),  // type
         false,                                          // is_const
@@ -2832,8 +2831,8 @@
       auto expr = MakeExpression(assignment.value);
       AddStatement(create<ast::AssignmentStatement>(
           Source{},
-          create<ast::IdentifierExpression>(
-              Source{}, ast_module_.RegisterSymbol(var_name)),
+          create<ast::IdentifierExpression>(Source{},
+                                            program_.RegisterSymbol(var_name)),
           expr.expr));
     }
   }
@@ -2871,7 +2870,7 @@
     AddStatement(create<ast::AssignmentStatement>(
         Source{},
         create<ast::IdentifierExpression>(Source{},
-                                          ast_module_.RegisterSymbol(name)),
+                                          program_.RegisterSymbol(name)),
         ast_expr.expr));
     return true;
   }
@@ -3010,7 +3009,7 @@
       TypedExpression expr{
           parser_impl_.ConvertType(inst.type_id()),
           create<ast::IdentifierExpression>(
-              Source{}, ast_module_.RegisterSymbol(def_info->phi_var))};
+              Source{}, program_.RegisterSymbol(def_info->phi_var))};
       return EmitConstDefOrWriteToHoistedVar(inst, expr);
     }
 
@@ -3073,7 +3072,7 @@
             create<ast::CallExpression>(
                 Source{},
                 create<ast::IdentifierExpression>(
-                    Source{}, ast_module_.RegisterSymbol(unary_builtin_name)),
+                    Source{}, program_.RegisterSymbol(unary_builtin_name)),
                 std::move(params))};
   }
 
@@ -3178,8 +3177,8 @@
     return {};
   }
 
-  auto* func = create<ast::IdentifierExpression>(
-      Source{}, ast_module_.RegisterSymbol(name));
+  auto* func = create<ast::IdentifierExpression>(Source{},
+                                                 program_.RegisterSymbol(name));
   ast::ExpressionList operands;
   type::Type* first_operand_type = nullptr;
   // All parameters to GLSL.std.450 extended instructions are IDs.
@@ -3205,20 +3204,20 @@
   }
   const char* names[] = {"x", "y", "z", "w"};
   return create<ast::IdentifierExpression>(
-      Source{}, ast_module_.RegisterSymbol(names[i & 3]));
+      Source{}, program_.RegisterSymbol(names[i & 3]));
 }
 
 ast::IdentifierExpression* FunctionEmitter::PrefixSwizzle(uint32_t n) {
   switch (n) {
     case 1:
       return create<ast::IdentifierExpression>(Source{},
-                                               ast_module_.RegisterSymbol("x"));
+                                               program_.RegisterSymbol("x"));
     case 2:
-      return create<ast::IdentifierExpression>(
-          Source{}, ast_module_.RegisterSymbol("xy"));
+      return create<ast::IdentifierExpression>(Source{},
+                                               program_.RegisterSymbol("xy"));
     case 3:
-      return create<ast::IdentifierExpression>(
-          Source{}, ast_module_.RegisterSymbol("xyz"));
+      return create<ast::IdentifierExpression>(Source{},
+                                               program_.RegisterSymbol("xyz"));
     default:
       break;
   }
@@ -3313,7 +3312,7 @@
 
       auto name = namer_.Name(base_id);
       current_expr.expr = create<ast::IdentifierExpression>(
-          Source{}, ast_module_.RegisterSymbol(name));
+          Source{}, program_.RegisterSymbol(name));
       current_expr.type = parser_impl_.ConvertType(ptr_ty_id);
     }
   }
@@ -3406,7 +3405,7 @@
         auto name =
             namer_.GetMemberName(pointee_type_id, uint32_t(index_const_val));
         auto* member_access = create<ast::IdentifierExpression>(
-            Source{}, ast_module_.RegisterSymbol(name));
+            Source{}, program_.RegisterSymbol(name));
 
         next_expr = create<ast::MemberAccessorExpression>(
             Source{}, current_expr.expr, member_access);
@@ -3527,7 +3526,7 @@
         }
         auto name = namer_.GetMemberName(current_type_id, uint32_t(index_val));
         auto* member_access = create<ast::IdentifierExpression>(
-            Source{}, ast_module_.RegisterSymbol(name));
+            Source{}, program_.RegisterSymbol(name));
 
         next_expr = create<ast::MemberAccessorExpression>(
             Source{}, current_expr.expr, member_access);
@@ -3700,7 +3699,7 @@
     // buffer pointer.
     const auto sc = GetStorageClassForPointerValue(result_id);
     if (ast_ptr_type->storage_class() != sc) {
-      return parser_impl_.get_module().create<type::Pointer>(
+      return parser_impl_.get_program().create<type::Pointer>(
           ast_ptr_type->type(), sc);
     }
   }
@@ -3932,7 +3931,7 @@
   // We ignore function attributes such as Inline, DontInline, Pure, Const.
   auto name = namer_.Name(inst.GetSingleWordInOperand(0));
   auto* function = create<ast::IdentifierExpression>(
-      Source{}, ast_module_.RegisterSymbol(name));
+      Source{}, program_.RegisterSymbol(name));
 
   ast::ExpressionList params;
   for (uint32_t iarg = 1; iarg < inst.NumInOperands(); ++iarg) {
@@ -3961,7 +3960,7 @@
   ss << intrinsic;
   auto name = ss.str();
   auto* ident = create<ast::IdentifierExpression>(
-      Source{}, ast_module_.RegisterSymbol(name));
+      Source{}, program_.RegisterSymbol(name));
   ident->set_intrinsic(intrinsic);
 
   ast::ExpressionList params;
@@ -4004,12 +4003,11 @@
     params.push_back(operand2.expr);
     // The condition goes last.
     params.push_back(condition.expr);
-    return {operand1.type,
-            create<ast::CallExpression>(
-                Source{},
-                create<ast::IdentifierExpression>(
-                    Source{}, ast_module_.RegisterSymbol("select")),
-                std::move(params))};
+    return {operand1.type, create<ast::CallExpression>(
+                               Source{},
+                               create<ast::IdentifierExpression>(
+                                   Source{}, program_.RegisterSymbol("select")),
+                               std::move(params))};
   }
   return {};
 }
@@ -4058,7 +4056,7 @@
   }
   auto name = namer_.Name(image->result_id());
   return create<ast::IdentifierExpression>(GetSourceForInst(inst),
-                                           ast_module_.RegisterSymbol(name));
+                                           program_.RegisterSymbol(name));
 }
 
 ast::Expression* FunctionEmitter::GetSamplerExpression(
@@ -4074,7 +4072,7 @@
   }
   auto name = namer_.Name(image->result_id());
   return create<ast::IdentifierExpression>(GetSourceForInst(inst),
-                                           ast_module_.RegisterSymbol(name));
+                                           program_.RegisterSymbol(name));
 }
 
 bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
@@ -4261,7 +4259,7 @@
   }
 
   auto* ident = create<ast::IdentifierExpression>(
-      Source{}, ast_module_.RegisterSymbol(builtin_name));
+      Source{}, program_.RegisterSymbol(builtin_name));
   auto* call_expr =
       create<ast::CallExpression>(Source{}, ident, std::move(params));
 
@@ -4569,14 +4567,14 @@
   }
 
   auto* member_ident = create<ast::IdentifierExpression>(
-      Source{}, ast_module_.RegisterSymbol(field_name));
+      Source{}, program_.RegisterSymbol(field_name));
   auto* member_access = create<ast::MemberAccessorExpression>(
       Source{}, MakeExpression(struct_ptr_id).expr, member_ident);
 
   // Generate the intrinsic function call.
   std::string call_ident_str = "arrayLength";
   auto* call_ident = create<ast::IdentifierExpression>(
-      Source{}, ast_module_.RegisterSymbol(call_ident_str));
+      Source{}, program_.RegisterSymbol(call_ident_str));
   call_ident->set_intrinsic(ast::Intrinsic::kArrayLength);
 
   ast::ExpressionList params{member_access};
diff --git a/src/reader/spirv/function.h b/src/reader/spirv/function.h
index 6650059..a7a0ddd 100644
--- a/src/reader/spirv/function.h
+++ b/src/reader/spirv/function.h
@@ -33,9 +33,9 @@
 #include "src/ast/case_statement.h"
 #include "src/ast/expression.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/statement.h"
 #include "src/ast/storage_class.h"
+#include "src/program.h"
 #include "src/reader/spirv/construct.h"
 #include "src/reader/spirv/entry_point_info.h"
 #include "src/reader/spirv/fail_stream.h"
@@ -345,9 +345,9 @@
   /// Constructor
   StatementBuilder() : Base(Source{}) {}
 
-  /// @param mod the ast Module to build into
-  /// @returns the build AST node
-  virtual ast::Statement* Build(ast::Module* mod) const = 0;
+  /// @param program the program to build into
+  /// @returns the built AST node
+  virtual ast::Statement* Build(Program* program) const = 0;
 
  private:
   bool IsValid() const override;
@@ -355,15 +355,15 @@
   void to_str(std::ostream& out, size_t indent) const override;
 };
 
-/// A FunctionEmitter emits a SPIR-V function onto a Tint AST module.
+/// A FunctionEmitter emits a SPIR-V function onto a Tint program.
 class FunctionEmitter {
  public:
-  /// Creates a FunctionEmitter, and prepares to write to the AST module
+  /// Creates a FunctionEmitter, and prepares to write to the program
   /// in `pi`
   /// @param pi a ParserImpl which has already executed BuildInternalModule
   /// @param function the function to emit
   FunctionEmitter(ParserImpl* pi, const spvtools::opt::Function& function);
-  /// Creates a FunctionEmitter, and prepares to write to the AST module
+  /// Creates a FunctionEmitter, and prepares to write to the program
   /// in `pi`
   /// @param pi a ParserImpl which has already executed BuildInternalModule
   /// @param function the function to emit
@@ -374,7 +374,7 @@
   /// Destructor
   ~FunctionEmitter();
 
-  /// Emits the function to AST module.
+  /// Emits the function to program.
   /// @return whether emission succeeded
   bool Emit();
 
@@ -964,8 +964,8 @@
     /// Replaces any StatementBuilders with the built result, and calls the
     /// completion callback (if set). Must only be called once, after all
     /// statements have been added with Add().
-    /// @param mod the module
-    void Finalize(ast::Module* mod);
+    /// @param program the program
+    void Finalize(Program* program);
 
     /// Add() adds `statement` to the block.
     /// Add() must not be called after calling Finalize().
@@ -1049,13 +1049,13 @@
   /// @returns the node pointer
   template <typename T, typename... ARGS>
   T* create(ARGS&&... args) const {
-    return ast_module_.create<T>(std::forward<ARGS>(args)...);
+    return program_.create<T>(std::forward<ARGS>(args)...);
   }
 
   using StatementsStack = std::vector<StatementBlock>;
 
   ParserImpl& parser_impl_;
-  ast::Module& ast_module_;
+  Program& program_;
   spvtools::opt::IRContext& ir_context_;
   spvtools::opt::analysis::DefUseManager* def_use_mgr_;
   spvtools::opt::analysis::ConstantManager* constant_mgr_;
diff --git a/src/reader/spirv/function_arithmetic_test.cc b/src/reader/spirv/function_arithmetic_test.cc
index b5c5f20..e034ed0 100644
--- a/src/reader/spirv/function_arithmetic_test.cc
+++ b/src/reader/spirv/function_arithmetic_test.cc
@@ -139,7 +139,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -151,7 +151,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryArithTest, SNegate_Int_Uint) {
@@ -166,7 +166,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -180,7 +180,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryArithTest, SNegate_Uint_Int) {
@@ -195,7 +195,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -209,7 +209,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryArithTest, SNegate_Uint_Uint) {
@@ -224,7 +224,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -240,7 +240,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryArithTest, SNegate_SignedVec_SignedVec) {
@@ -255,7 +255,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -271,7 +271,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryArithTest, SNegate_SignedVec_UnsignedVec) {
@@ -286,7 +286,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -304,7 +304,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryArithTest, SNegate_UnsignedVec_SignedVec) {
@@ -319,7 +319,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -337,7 +337,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryArithTest, SNegate_UnsignedVec_UnsignedVec) {
@@ -352,7 +352,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -372,7 +372,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryArithTest, FNegate_Scalar) {
@@ -387,7 +387,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -399,7 +399,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryArithTest, FNegate_Vector) {
@@ -414,7 +414,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -430,7 +430,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 struct BinaryData {
@@ -478,7 +478,7 @@
      << GetParam().ast_type << "\n    {\n      Binary[not set]{"
      << "\n        " << GetParam().ast_lhs << "\n        " << GetParam().ast_op
      << "\n        " << GetParam().ast_rhs;
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(ss.str()))
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(ss.str()))
       << assembly;
 }
 
@@ -701,7 +701,7 @@
       << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -736,7 +736,7 @@
       << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -759,7 +759,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 INSTANTIATE_TEST_SUITE_P(
@@ -847,7 +847,7 @@
       << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -882,7 +882,7 @@
       << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -905,7 +905,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 INSTANTIATE_TEST_SUITE_P(
@@ -935,7 +935,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_10
     none
@@ -948,7 +948,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvBinaryArithTestBasic, MatrixTimesScalar) {
@@ -965,7 +965,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_10
     none
@@ -978,7 +978,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvBinaryArithTestBasic, VectorTimesMatrix) {
@@ -995,7 +995,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_10
     none
@@ -1008,7 +1008,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvBinaryArithTestBasic, MatrixTimesVector) {
@@ -1025,7 +1025,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_10
     none
@@ -1038,7 +1038,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvBinaryArithTestBasic, MatrixTimesMatrix) {
@@ -1055,7 +1055,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_10
     none
@@ -1068,7 +1068,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvBinaryArithTestBasic, Dot) {
@@ -1085,7 +1085,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_3
     none
@@ -1100,7 +1100,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvBinaryArithTestBasic, OuterProduct) {
@@ -1119,7 +1119,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(got, HasSubstr(R"(VariableConst{
     x_3
     none
diff --git a/src/reader/spirv/function_bit_test.cc b/src/reader/spirv/function_bit_test.cc
index 3565456..b54067d 100644
--- a/src/reader/spirv/function_bit_test.cc
+++ b/src/reader/spirv/function_bit_test.cc
@@ -163,7 +163,7 @@
      << GetParam().ast_type << "\n    {\n      Binary[not set]{"
      << "\n        " << GetParam().ast_lhs << "\n        " << GetParam().ast_op
      << "\n        " << GetParam().ast_rhs;
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(ss.str()))
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(ss.str()))
       << assembly;
 }
 
@@ -401,7 +401,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -413,7 +413,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryBitTest, Not_Int_Uint) {
@@ -428,7 +428,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -442,7 +442,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryBitTest, Not_Uint_Int) {
@@ -457,7 +457,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -471,7 +471,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryBitTest, Not_Uint_Uint) {
@@ -486,7 +486,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -498,7 +498,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryBitTest, Not_SignedVec_SignedVec) {
@@ -513,7 +513,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -529,7 +529,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryBitTest, Not_SignedVec_UnsignedVec) {
@@ -544,7 +544,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -562,7 +562,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryBitTest, Not_UnsignedVec_SignedVec) {
@@ -577,7 +577,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -595,7 +595,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 TEST_F(SpvUnaryBitTest, Not_UnsignedVec_UnsignedVec) {
   const auto assembly = CommonTypes() + R"(
@@ -609,7 +609,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -625,7 +625,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 std::string BitTestPreamble() {
@@ -664,7 +664,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  const auto body = ToString(p->get_module(), fe.ast_body());
+  const auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
@@ -692,7 +692,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  const auto body = ToString(p->get_module(), fe.ast_body());
+  const auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
@@ -722,7 +722,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  const auto body = ToString(p->get_module(), fe.ast_body());
+  const auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
@@ -752,7 +752,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  const auto body = ToString(p->get_module(), fe.ast_body());
+  const auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
@@ -780,7 +780,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  const auto body = ToString(p->get_module(), fe.ast_body());
+  const auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
@@ -808,7 +808,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  const auto body = ToString(p->get_module(), fe.ast_body());
+  const auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
@@ -838,7 +838,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  const auto body = ToString(p->get_module(), fe.ast_body());
+  const auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
@@ -868,7 +868,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  const auto body = ToString(p->get_module(), fe.ast_body());
+  const auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
@@ -896,7 +896,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  const auto body = ToString(p->get_module(), fe.ast_body());
+  const auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
@@ -924,7 +924,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  const auto body = ToString(p->get_module(), fe.ast_body());
+  const auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
@@ -954,7 +954,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  const auto body = ToString(p->get_module(), fe.ast_body());
+  const auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
@@ -984,7 +984,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  const auto body = ToString(p->get_module(), fe.ast_body());
+  const auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
@@ -1012,7 +1012,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  const auto body = ToString(p->get_module(), fe.ast_body());
+  const auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
@@ -1040,7 +1040,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  const auto body = ToString(p->get_module(), fe.ast_body());
+  const auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
@@ -1070,7 +1070,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  const auto body = ToString(p->get_module(), fe.ast_body());
+  const auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
@@ -1100,7 +1100,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  const auto body = ToString(p->get_module(), fe.ast_body());
+  const auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
diff --git a/src/reader/spirv/function_call_test.cc b/src/reader/spirv/function_call_test.cc
index 251bafc..d830d7c 100644
--- a/src/reader/spirv/function_call_test.cc
+++ b/src/reader/spirv/function_call_test.cc
@@ -46,8 +46,8 @@
      OpFunctionEnd
   )"));
   ASSERT_TRUE(p->BuildAndParseInternalModule()) << p->error();
-  const auto module_ast_str = p->get_module().to_str();
-  EXPECT_THAT(module_ast_str, Eq(R"(Module{
+  const auto program_ast_str = p->get_program().to_str();
+  EXPECT_THAT(program_ast_str, Eq(R"(Module{
   Function tint_symbol_1 -> __void
   ()
   {
@@ -64,7 +64,7 @@
     Return{}
   }
 }
-)")) << module_ast_str;
+)")) << program_ast_str;
 }
 
 TEST_F(SpvParserTest, EmitStatement_ScalarCallNoParams) {
@@ -90,7 +90,7 @@
   {
     FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
     EXPECT_TRUE(fe.EmitBody());
-    EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+    EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
                 HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_1
@@ -106,17 +106,17 @@
   }
 }
 Return{})"))
-        << ToString(p->get_module(), fe.ast_body());
+        << ToString(p->get_program(), fe.ast_body());
   }
 
   {
     FunctionEmitter fe(p.get(), *spirv_function(p.get(), 50));
     EXPECT_TRUE(fe.EmitBody());
-    EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(Return{
+    EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(Return{
   {
     ScalarConstructor[not set]{42}
   }
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
   }
 }
 
@@ -147,7 +147,7 @@
   {
     FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
     EXPECT_TRUE(fe.EmitBody()) << p->error();
-    EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+    EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
                 HasSubstr(R"(VariableDeclStatement{
   Variable{
     x_10
@@ -178,16 +178,16 @@
   Identifier[not set]{x_1}
 }
 Return{})"))
-        << ToString(p->get_module(), fe.ast_body());
+        << ToString(p->get_program(), fe.ast_body());
   }
   {
     FunctionEmitter fe(p.get(), *spirv_function(p.get(), 50));
     EXPECT_TRUE(fe.EmitBody()) << p->error();
-    EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(Return{
+    EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(Return{
   {
     ScalarConstructor[not set]{42}
   }
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
   }
 }
 
@@ -216,9 +216,9 @@
   )"));
   ASSERT_TRUE(p->BuildAndParseInternalModule()) << p->error();
   EXPECT_TRUE(p->error().empty());
-  const auto module_ast_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
-  EXPECT_THAT(module_ast_str, HasSubstr(R"(Module{
+  const auto program_ast_str =
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
+  EXPECT_THAT(program_ast_str, HasSubstr(R"(Module{
   Function x_50 -> __u32
   (
     VariableConst{
@@ -264,7 +264,7 @@
     }
     Return{}
   }
-})")) << module_ast_str;
+})")) << program_ast_str;
 }
 
 }  // namespace
diff --git a/src/reader/spirv/function_cfg_test.cc b/src/reader/spirv/function_cfg_test.cc
index cc5bdf9..693dbe6 100644
--- a/src/reader/spirv/function_cfg_test.cc
+++ b/src/reader/spirv/function_cfg_test.cc
@@ -7361,7 +7361,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -7473,7 +7473,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -7600,7 +7600,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error() << assembly;
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -7791,7 +7791,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(If{
   (
     ScalarConstructor[not set]{false}
@@ -7827,7 +7827,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -7875,7 +7875,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -7931,7 +7931,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -7998,7 +7998,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -8070,7 +8070,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -8134,7 +8134,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -8219,7 +8219,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -8309,7 +8309,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -8364,7 +8364,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -8415,7 +8415,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -8458,7 +8458,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -8509,7 +8509,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -8574,7 +8574,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -8648,7 +8648,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -8720,7 +8720,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -8778,7 +8778,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Loop{
   Assignment{
     Identifier[not set]{var_1}
@@ -8838,7 +8838,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Loop{
   Assignment{
     Identifier[not set]{var_1}
@@ -8905,7 +8905,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Loop{
   Assignment{
     Identifier[not set]{var_1}
@@ -8979,7 +8979,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Loop{
   If{
     (
@@ -9037,7 +9037,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Loop{
   Assignment{
     Identifier[not set]{var_1}
@@ -9086,7 +9086,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Loop{
   Assignment{
     Identifier[not set]{var_1}
@@ -9142,7 +9142,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Loop{
   Assignment{
     Identifier[not set]{var_1}
@@ -9204,7 +9204,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Loop{
   Assignment{
     Identifier[not set]{var_1}
@@ -9266,7 +9266,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Loop{
   Assignment{
     Identifier[not set]{var_1}
@@ -9319,7 +9319,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -9364,7 +9364,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -9418,7 +9418,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -9478,7 +9478,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -9544,7 +9544,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -9615,7 +9615,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -9687,7 +9687,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -9757,7 +9757,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -9809,7 +9809,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Return{}
 )";
   ASSERT_EQ(expect, got);
@@ -9835,7 +9835,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(If{
   (
     ScalarConstructor[not set]{false}
@@ -9875,7 +9875,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Loop{
   Return{}
 }
@@ -9905,7 +9905,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 200));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Return{
   {
     ScalarConstructor[not set]{2}
@@ -9944,7 +9944,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 200));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(If{
   (
     ScalarConstructor[not set]{false}
@@ -10001,7 +10001,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 200));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Loop{
   Return{
     {
@@ -10031,7 +10031,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Discard{}
 )";
   ASSERT_EQ(expect, got);
@@ -10057,7 +10057,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(If{
   (
     ScalarConstructor[not set]{false}
@@ -10097,7 +10097,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Loop{
   Discard{}
 }
@@ -10119,7 +10119,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Return{}
 )";
   ASSERT_EQ(expect, got);
@@ -10145,7 +10145,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(If{
   (
     ScalarConstructor[not set]{false}
@@ -10185,7 +10185,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Loop{
   Return{}
 }
@@ -10215,7 +10215,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 200));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Return{
   {
     ScalarConstructor[not set]{0}
@@ -10249,7 +10249,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Loop{
   continuing {
     Assignment{
@@ -10284,7 +10284,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Loop{
   Assignment{
     Identifier[not set]{var_1}
@@ -10321,7 +10321,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -10381,7 +10381,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -10452,7 +10452,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Loop{
   Assignment{
     Identifier[not set]{var_1}
@@ -10534,7 +10534,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Loop{
   continuing {
     Assignment{
@@ -10576,7 +10576,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Loop{
   Assignment{
     Identifier[not set]{var_1}
@@ -10630,7 +10630,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Loop{
   If{
     (
@@ -10699,7 +10699,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -10769,7 +10769,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(If{
   (
     ScalarConstructor[not set]{false}
@@ -10812,7 +10812,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(If{
   (
     ScalarConstructor[not set]{false}
@@ -10864,7 +10864,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -10915,7 +10915,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -11019,7 +11019,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -11062,7 +11062,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -11113,7 +11113,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -11171,7 +11171,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -11227,7 +11227,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -11287,7 +11287,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -11348,7 +11348,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -11431,7 +11431,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -11526,7 +11526,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -11611,7 +11611,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -11680,7 +11680,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -11747,7 +11747,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -11821,7 +11821,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -11890,7 +11890,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -11948,7 +11948,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -12021,7 +12021,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -12117,7 +12117,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -12256,7 +12256,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -12337,7 +12337,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -12405,7 +12405,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -12462,7 +12462,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -12534,7 +12534,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -12622,7 +12622,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -12701,7 +12701,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -12789,7 +12789,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -12886,7 +12886,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -12982,7 +12982,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -13091,7 +13091,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -13188,7 +13188,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -13269,7 +13269,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -13333,7 +13333,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{0}
@@ -13418,7 +13418,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -13509,7 +13509,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{var_1}
   ScalarConstructor[not set]{1}
@@ -13578,7 +13578,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = "unhandled case";
   ASSERT_EQ(expect, got);
 }
@@ -13613,7 +13613,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = "unhandled case";
   ASSERT_EQ(expect, got);
 }
diff --git a/src/reader/spirv/function_composite_test.cc b/src/reader/spirv/function_composite_test.cc
index b8f004b..d292742 100644
--- a/src/reader/spirv/function_composite_test.cc
+++ b/src/reader/spirv/function_composite_test.cc
@@ -86,7 +86,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_1
@@ -128,7 +128,7 @@
       }
     }
   }
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTest_Composite_Construct, Matrix) {
@@ -143,7 +143,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -169,7 +169,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTest_Composite_Construct, Array) {
@@ -184,7 +184,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -200,7 +200,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTest_Composite_Construct, Struct) {
@@ -215,7 +215,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -233,7 +233,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 using SpvParserTest_CompositeExtract = SpvParserTest;
@@ -250,7 +250,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -266,7 +266,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTest_CompositeExtract, Vector_IndexTooBigError) {
@@ -301,7 +301,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_2
     none
@@ -313,7 +313,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTest_CompositeExtract, Matrix_IndexTooBigError) {
@@ -352,7 +352,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_2
     none
@@ -367,7 +367,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTest_CompositeExtract, Array) {
@@ -386,7 +386,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_2
     none
@@ -398,7 +398,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTest_CompositeExtract, RuntimeArray_IsError) {
@@ -437,7 +437,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_2
     none
@@ -449,7 +449,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTest_CompositeExtract, Struct_DifferOnlyInMemberName) {
@@ -480,7 +480,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
   auto got = fe.ast_body();
-  EXPECT_THAT(ToString(p->get_module(), got), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), got), HasSubstr(R"(
   VariableConst{
     x_2
     none
@@ -492,8 +492,8 @@
       }
     }
   })"))
-      << ToString(p->get_module(), got);
-  EXPECT_THAT(ToString(p->get_module(), got), HasSubstr(R"(
+      << ToString(p->get_program(), got);
+  EXPECT_THAT(ToString(p->get_program(), got), HasSubstr(R"(
   VariableConst{
     x_4
     none
@@ -505,7 +505,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), got);
+      << ToString(p->get_program(), got);
 }
 
 TEST_F(SpvParserTest_CompositeExtract, Struct_IndexTooBigError) {
@@ -546,7 +546,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_2
     none
@@ -567,7 +567,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 using SpvParserTest_CopyObject = SpvParserTest;
@@ -585,7 +585,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_1
@@ -605,7 +605,7 @@
       Identifier[not set]{x_1}
     }
   }
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTest_CopyObject, Pointer) {
@@ -624,7 +624,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_1
@@ -644,7 +644,7 @@
       Identifier[not set]{x_1}
     }
   }
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
 }
 
 using SpvParserTest_VectorShuffle = SpvParserTest;
@@ -665,7 +665,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_10
     none
@@ -692,7 +692,7 @@
       }
     }
   }
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTest_VectorShuffle, ConstantOperands_UseBoth) {
@@ -708,7 +708,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_10
     none
@@ -751,7 +751,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTest_VectorShuffle, ConstantOperands_AllOnesMapToNull) {
@@ -768,7 +768,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_10
     none
@@ -784,7 +784,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTest_VectorShuffle, IndexTooBig_IsError) {
diff --git a/src/reader/spirv/function_conversion_test.cc b/src/reader/spirv/function_conversion_test.cc
index 5499451..1e352a2 100644
--- a/src/reader/spirv/function_conversion_test.cc
+++ b/src/reader/spirv/function_conversion_test.cc
@@ -82,7 +82,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -93,7 +93,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryConversionTest, Bitcast_Vector) {
@@ -108,7 +108,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -123,7 +123,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryConversionTest, ConvertSToF_BadArg) {
@@ -238,7 +238,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_1
     none
@@ -250,7 +250,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryConversionTest, ConvertSToF_Scalar_FromUnsigned) {
@@ -266,7 +266,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_1
     none
@@ -280,7 +280,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryConversionTest, ConvertSToF_Vector_FromSigned) {
@@ -296,7 +296,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_1
     none
@@ -308,7 +308,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryConversionTest, ConvertSToF_Vector_FromUnsigned) {
@@ -324,7 +324,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_1
     none
@@ -338,7 +338,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryConversionTest, ConvertUToF_Scalar_BadArgType) {
@@ -387,7 +387,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_1
     none
@@ -401,7 +401,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryConversionTest, ConvertUToF_Scalar_FromUnsigned) {
@@ -417,7 +417,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_1
     none
@@ -429,7 +429,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryConversionTest, ConvertUToF_Vector_FromSigned) {
@@ -445,7 +445,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_1
     none
@@ -459,7 +459,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryConversionTest, ConvertUToF_Vector_FromUnsigned) {
@@ -475,7 +475,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_1
     none
@@ -487,7 +487,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryConversionTest, ConvertFToS_Scalar_BadArgType) {
@@ -537,7 +537,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_1
     none
@@ -549,7 +549,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryConversionTest, ConvertFToS_Scalar_ToUnsigned) {
@@ -565,7 +565,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_1
     none
@@ -579,7 +579,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryConversionTest, ConvertFToS_Vector_ToSigned) {
@@ -595,7 +595,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_1
     none
@@ -607,7 +607,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryConversionTest, ConvertFToS_Vector_ToUnsigned) {
@@ -623,7 +623,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_1
     none
@@ -637,7 +637,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryConversionTest, ConvertFToU_Scalar_BadArgType) {
@@ -687,7 +687,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_1
     none
@@ -701,7 +701,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryConversionTest, ConvertFToU_Scalar_ToUnsigned) {
@@ -717,7 +717,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_1
     none
@@ -729,7 +729,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryConversionTest, ConvertFToU_Vector_ToSigned) {
@@ -745,7 +745,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_1
     none
@@ -759,7 +759,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryConversionTest, ConvertFToU_Vector_ToUnsigned) {
@@ -775,7 +775,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableConst{
     x_1
     none
@@ -787,7 +787,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 // TODO(dneto): OpSConvert // only if multiple widths
diff --git a/src/reader/spirv/function_decl_test.cc b/src/reader/spirv/function_decl_test.cc
index 164ab13..6d83356 100644
--- a/src/reader/spirv/function_decl_test.cc
+++ b/src/reader/spirv/function_decl_test.cc
@@ -59,7 +59,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.Emit());
-  auto got = Demangler().Demangle(p->get_module(), p->get_module().to_str());
+  auto got = Demangler().Demangle(p->get_program(), p->get_program().to_str());
   std::string expect = R"(Module{
   Function x_100 -> __void
   ()
@@ -83,7 +83,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.Emit());
 
-  auto got = Demangler().Demangle(p->get_module(), p->get_module().to_str());
+  auto got = Demangler().Demangle(p->get_program(), p->get_program().to_str());
   std::string expect = R"(Module{
   Function x_100 -> __f32
   ()
@@ -115,7 +115,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.Emit());
 
-  auto got = Demangler().Demangle(p->get_module(), p->get_module().to_str());
+  auto got = Demangler().Demangle(p->get_program(), p->get_program().to_str());
   std::string expect = R"(Module{
   Function x_100 -> __void
   (
@@ -159,7 +159,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.Emit());
 
-  auto got = Demangler().Demangle(p->get_module(), p->get_module().to_str());
+  auto got = Demangler().Demangle(p->get_program(), p->get_program().to_str());
   std::string expect = R"(Module{
   Function x_100 -> __void
   (
diff --git a/src/reader/spirv/function_glsl_std_450_test.cc b/src/reader/spirv/function_glsl_std_450_test.cc
index 78f7932..0706ec6 100644
--- a/src/reader/spirv/function_glsl_std_450_test.cc
+++ b/src/reader/spirv/function_glsl_std_450_test.cc
@@ -183,7 +183,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -191,14 +191,14 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{f1}
         )
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_P(SpvParserTest_GlslStd450_Float_Floating, Vector) {
@@ -212,7 +212,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -220,14 +220,14 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{v2f1}
         )
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_P(SpvParserTest_GlslStd450_Float_FloatingFloating, Scalar) {
@@ -241,7 +241,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -249,7 +249,7 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{f1}
           Identifier[not set]{f2}
@@ -257,7 +257,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_P(SpvParserTest_GlslStd450_Float_FloatingFloating, Vector) {
@@ -271,7 +271,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -279,7 +279,7 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{v2f1}
           Identifier[not set]{v2f2}
@@ -287,7 +287,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_P(SpvParserTest_GlslStd450_Floating_Floating, Scalar) {
@@ -301,7 +301,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -309,14 +309,14 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{f1}
         )
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_P(SpvParserTest_GlslStd450_Floating_Floating, Vector) {
@@ -330,7 +330,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -338,14 +338,14 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{v2f1}
         )
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_P(SpvParserTest_GlslStd450_Floating_FloatingFloating, Scalar) {
@@ -359,7 +359,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -367,7 +367,7 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{f1}
           Identifier[not set]{f2}
@@ -375,7 +375,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_P(SpvParserTest_GlslStd450_Floating_FloatingFloating, Vector) {
@@ -389,7 +389,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -397,7 +397,7 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{v2f1}
           Identifier[not set]{v2f2}
@@ -405,7 +405,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_P(SpvParserTest_GlslStd450_Floating_FloatingFloatingFloating, Scalar) {
@@ -419,7 +419,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -427,7 +427,7 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{f1}
           Identifier[not set]{f2}
@@ -436,7 +436,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_P(SpvParserTest_GlslStd450_Floating_FloatingFloatingFloating, Vector) {
@@ -451,7 +451,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -459,7 +459,7 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{v2f1}
           Identifier[not set]{v2f2}
@@ -468,7 +468,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_P(SpvParserTest_GlslStd450_Floating_FloatingUinting, Scalar) {
@@ -482,7 +482,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -490,7 +490,7 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{f1}
           Identifier[not set]{u1}
@@ -498,7 +498,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_P(SpvParserTest_GlslStd450_Floating_FloatingUinting, Vector) {
@@ -513,7 +513,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -521,7 +521,7 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{v2f1}
           Identifier[not set]{v2u1}
@@ -529,7 +529,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_P(SpvParserTest_GlslStd450_Floating_FloatingInting, Scalar) {
@@ -543,7 +543,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -551,7 +551,7 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{f1}
           Identifier[not set]{i1}
@@ -559,7 +559,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_P(SpvParserTest_GlslStd450_Floating_FloatingInting, Vector) {
@@ -574,7 +574,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -582,7 +582,7 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{v2f1}
           Identifier[not set]{v2i1}
@@ -590,7 +590,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_P(SpvParserTest_GlslStd450_Float3_Float3Float3, Samples) {
@@ -605,7 +605,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -613,7 +613,7 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{v3f1}
           Identifier[not set]{v3f2}
@@ -621,7 +621,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 INSTANTIATE_TEST_SUITE_P(Samples,
@@ -709,7 +709,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -717,14 +717,14 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{i1}
         )
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_P(SpvParserTest_GlslStd450_Inting_Inting, Vector) {
@@ -739,7 +739,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -747,14 +747,14 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{v2i1}
         )
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_P(SpvParserTest_GlslStd450_Inting_IntingInting, Scalar) {
@@ -769,7 +769,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -777,7 +777,7 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{i1}
           Identifier[not set]{i2}
@@ -785,7 +785,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_P(SpvParserTest_GlslStd450_Inting_IntingInting, Vector) {
@@ -800,7 +800,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -808,7 +808,7 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{v2i1}
           Identifier[not set]{v2i2}
@@ -816,7 +816,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_P(SpvParserTest_GlslStd450_Inting_IntingIntingInting, Scalar) {
@@ -831,7 +831,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -839,7 +839,7 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{i1}
           Identifier[not set]{i2}
@@ -848,7 +848,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_P(SpvParserTest_GlslStd450_Inting_IntingIntingInting, Vector) {
@@ -863,7 +863,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -871,7 +871,7 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{v2i1}
           Identifier[not set]{v2i2}
@@ -880,7 +880,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 INSTANTIATE_TEST_SUITE_P(Samples,
@@ -907,7 +907,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -915,7 +915,7 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{u1}
           Identifier[not set]{u2}
@@ -923,7 +923,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_P(SpvParserTest_GlslStd450_Uinting_UintingUinting, Vector) {
@@ -938,7 +938,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -946,7 +946,7 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{v2u1}
           Identifier[not set]{v2u2}
@@ -954,7 +954,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_P(SpvParserTest_GlslStd450_Uinting_UintingUintingUinting, Scalar) {
@@ -968,7 +968,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -976,7 +976,7 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{u1}
           Identifier[not set]{u2}
@@ -985,7 +985,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_P(SpvParserTest_GlslStd450_Uinting_UintingUintingUinting, Vector) {
@@ -1000,7 +1000,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -1008,7 +1008,7 @@
     {
       Call[not set]{
         Identifier[not set]{)" + GetParam().wgsl_func +
-                                                                  R"(}
+                                                                   R"(}
         (
           Identifier[not set]{v2u1}
           Identifier[not set]{v2u2}
@@ -1017,7 +1017,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 INSTANTIATE_TEST_SUITE_P(Samples,
@@ -1043,7 +1043,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto body = ToString(p->get_module(), fe.ast_body());
+  auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
@@ -1095,7 +1095,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto body = ToString(p->get_module(), fe.ast_body());
+  auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
@@ -1153,7 +1153,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto body = ToString(p->get_module(), fe.ast_body());
+  auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
@@ -1211,7 +1211,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto body = ToString(p->get_module(), fe.ast_body());
+  auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
@@ -1271,7 +1271,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto body = ToString(p->get_module(), fe.ast_body());
+  auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
@@ -1329,7 +1329,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto body = ToString(p->get_module(), fe.ast_body());
+  auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
@@ -1387,7 +1387,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  auto body = ToString(p->get_module(), fe.ast_body());
+  auto body = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body, HasSubstr(R"(
   VariableConst{
     x_1
diff --git a/src/reader/spirv/function_logical_test.cc b/src/reader/spirv/function_logical_test.cc
index e5171cf..6cb1f14 100644
--- a/src/reader/spirv/function_logical_test.cc
+++ b/src/reader/spirv/function_logical_test.cc
@@ -206,7 +206,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -218,7 +218,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvUnaryLogicalTest, LogicalNot_Vector) {
@@ -233,7 +233,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -249,7 +249,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 struct BinaryData {
@@ -296,7 +296,7 @@
      << GetParam().ast_type << "\n    {\n      Binary[not set]{"
      << "\n        " << GetParam().ast_lhs << "\n        " << GetParam().ast_op
      << "\n        " << GetParam().ast_rhs;
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(ss.str()))
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(ss.str()))
       << assembly;
 }
 
@@ -702,7 +702,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -718,7 +718,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvFUnordTest, FUnordEqual_Vector) {
@@ -733,7 +733,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -757,7 +757,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvFUnordTest, FUnordNotEqual_Scalar) {
@@ -772,7 +772,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -788,7 +788,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvFUnordTest, FUnordNotEqual_Vector) {
@@ -803,7 +803,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -827,7 +827,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvFUnordTest, FUnordLessThan_Scalar) {
@@ -842,7 +842,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -858,7 +858,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvFUnordTest, FUnordLessThan_Vector) {
@@ -873,7 +873,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -897,7 +897,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvFUnordTest, FUnordLessThanEqual_Scalar) {
@@ -912,7 +912,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -928,7 +928,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvFUnordTest, FUnordLessThanEqual_Vector) {
@@ -943,7 +943,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -967,7 +967,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvFUnordTest, FUnordGreaterThan_Scalar) {
@@ -982,7 +982,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -998,7 +998,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvFUnordTest, FUnordGreaterThan_Vector) {
@@ -1013,7 +1013,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -1037,7 +1037,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvFUnordTest, FUnordGreaterThanEqual_Scalar) {
@@ -1052,7 +1052,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -1068,7 +1068,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvFUnordTest, FUnordGreaterThanEqual_Vector) {
@@ -1083,7 +1083,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -1107,7 +1107,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvFUnordTest, Select_BoolCond_BoolParams) {
@@ -1122,7 +1122,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_1
@@ -1139,7 +1139,7 @@
       }
     }
   }
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvFUnordTest, Select_BoolCond_IntScalarParams) {
@@ -1154,7 +1154,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_1
@@ -1171,7 +1171,7 @@
       }
     }
   }
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvFUnordTest, Select_BoolCond_FloatScalarParams) {
@@ -1186,7 +1186,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_1
@@ -1203,7 +1203,7 @@
       }
     }
   }
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvFUnordTest, Select_BoolCond_VectorParams) {
@@ -1218,7 +1218,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_1
@@ -1243,7 +1243,7 @@
       }
     }
   }
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvFUnordTest, Select_VecBoolCond_VectorParams) {
@@ -1258,7 +1258,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_1
@@ -1287,7 +1287,7 @@
       }
     }
   }
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
 }
 
 using SpvLogicalTest = SpvParserTestBase<::testing::Test>;
@@ -1304,7 +1304,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_1
@@ -1323,7 +1323,7 @@
       }
     }
   }
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvLogicalTest, All) {
@@ -1338,7 +1338,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_1
@@ -1357,7 +1357,7 @@
       }
     }
   }
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvLogicalTest, IsNan_Scalar) {
@@ -1372,7 +1372,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_1
@@ -1387,7 +1387,7 @@
       }
     }
   }
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvLogicalTest, IsNan_Vector) {
@@ -1402,7 +1402,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_1
@@ -1421,7 +1421,7 @@
       }
     }
   }
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvLogicalTest, IsInf_Scalar) {
@@ -1436,7 +1436,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_1
@@ -1451,7 +1451,7 @@
       }
     }
   }
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvLogicalTest, IsInf_Vector) {
@@ -1466,7 +1466,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_1
@@ -1485,7 +1485,7 @@
       }
     }
   }
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
 }
 
 // TODO(dneto): Kernel-guarded instructions.
diff --git a/src/reader/spirv/function_memory_test.cc b/src/reader/spirv/function_memory_test.cc
index 29023df..bc9e7f9 100644
--- a/src/reader/spirv/function_memory_test.cc
+++ b/src/reader/spirv/function_memory_test.cc
@@ -51,7 +51,8 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(Assignment{
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
+              HasSubstr(R"(Assignment{
   Identifier[not set]{x_1}
   ScalarConstructor[not set]{true}
 }
@@ -83,7 +84,8 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody());
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(Assignment{
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
+              HasSubstr(R"(Assignment{
   Identifier[not set]{x_1}
   ScalarConstructor[not set]{42}
 }
@@ -111,7 +113,8 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody());
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(Assignment{
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
+              HasSubstr(R"(Assignment{
   Identifier[not set]{x_1}
   ScalarConstructor[not set]{42}
 }
@@ -139,7 +142,8 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody());
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(Assignment{
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
+              HasSubstr(R"(Assignment{
   Identifier[not set]{x_1}
   ScalarConstructor[not set]{42.000000}
 }
@@ -168,7 +172,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_2
     none
@@ -197,7 +201,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_2
@@ -239,7 +243,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_2
@@ -277,7 +281,8 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody());
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(Assignment{
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
+              HasSubstr(R"(Assignment{
   Identifier[not set]{x_1}
   ScalarConstructor[not set]{42}
 })"));
@@ -344,13 +349,14 @@
       << assembly << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody());
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(Assignment{
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
+              HasSubstr(R"(Assignment{
   MemberAccessor[not set]{
     Identifier[not set]{myvar}
     Identifier[not set]{z}
   }
   ScalarConstructor[not set]{42}
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTest, EmitStatement_AccessChain_VectorConstOutOfBounds) {
@@ -407,7 +413,8 @@
       << assembly << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody());
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(Assignment{
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
+              HasSubstr(R"(Assignment{
   ArrayAccessor[not set]{
     Identifier[not set]{myvar}
     Identifier[not set]{x_11}
@@ -444,7 +451,8 @@
       << assembly << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody());
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(Assignment{
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
+              HasSubstr(R"(Assignment{
   ArrayAccessor[not set]{
     Identifier[not set]{myvar}
     ScalarConstructor[not set]{2}
@@ -487,7 +495,8 @@
       << assembly << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody());
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(Assignment{
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
+              HasSubstr(R"(Assignment{
   ArrayAccessor[not set]{
     Identifier[not set]{myvar}
     ScalarConstructor[not set]{2}
@@ -529,7 +538,8 @@
       << assembly << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody());
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(Assignment{
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
+              HasSubstr(R"(Assignment{
   MemberAccessor[not set]{
     Identifier[not set]{myvar}
     Identifier[not set]{age}
@@ -577,7 +587,8 @@
       << assembly << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody());
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(Assignment{
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
+              HasSubstr(R"(Assignment{
   MemberAccessor[not set]{
     Identifier[not set]{myvar}
     Identifier[not set]{age}
@@ -590,7 +601,7 @@
     Identifier[not set]{ancientness}
   }
   ScalarConstructor[not set]{420.000000}
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTest, EmitStatement_AccessChain_StructNonConstIndex) {
@@ -687,7 +698,8 @@
       << assembly << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody());
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(Assignment{
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
+              HasSubstr(R"(Assignment{
   ArrayAccessor[not set]{
     MemberAccessor[not set]{
       Identifier[not set]{myvar}
@@ -727,7 +739,8 @@
       << assembly << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody());
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(Assignment{
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
+              HasSubstr(R"(Assignment{
   MemberAccessor[not set]{
     ArrayAccessor[not set]{
       Identifier[not set]{myvar}
@@ -801,7 +814,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions())
       << assembly << p->error();
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
   RTArr -> __array__u32_stride_4
   S Struct{
@@ -836,7 +849,8 @@
   ASSERT_TRUE(p->BuildAndParseInternalModule()) << assembly << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(Assignment{
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
+              HasSubstr(R"(Assignment{
   MemberAccessor[not set]{
     Identifier[not set]{myvar}
     Identifier[not set]{field0}
@@ -852,7 +866,7 @@
     ScalarConstructor[not set]{1}
   }
   ScalarConstructor[not set]{0}
-})")) << ToString(p->get_module(), fe.ast_body())
+})")) << ToString(p->get_program(), fe.ast_body())
       << p->error();
 }
 
@@ -875,7 +889,8 @@
   ASSERT_TRUE(p->BuildAndParseInternalModule()) << assembly << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(Assignment{
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
+              HasSubstr(R"(Assignment{
   ArrayAccessor[not set]{
     MemberAccessor[not set]{
       Identifier[not set]{myvar}
@@ -884,7 +899,7 @@
     ScalarConstructor[not set]{1}
   }
   ScalarConstructor[not set]{0}
-})")) << ToString(p->get_module(), fe.ast_body())
+})")) << ToString(p->get_program(), fe.ast_body())
       << p->error();
 }
 
@@ -908,7 +923,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModule()) << assembly << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_2
@@ -928,7 +943,7 @@
 Assignment{
   Identifier[not set]{x_2}
   ScalarConstructor[not set]{0}
-})")) << ToString(p->get_module(), fe.ast_body())
+})")) << ToString(p->get_program(), fe.ast_body())
       << p->error();
 }
 
@@ -964,7 +979,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModule()) << assembly << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               Eq(R"(VariableDeclStatement{
   Variable{
     x_2
@@ -999,7 +1014,7 @@
   ScalarConstructor[not set]{0}
 }
 Return{}
-)")) << ToString(p->get_module(), fe.ast_body())
+)")) << ToString(p->get_program(), fe.ast_body())
      << p->error();
 }
 
@@ -1052,7 +1067,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModule()) << assembly << p->error();
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  const auto body_str = ToString(p->get_module(), fe.ast_body());
+  const auto body_str = ToString(p->get_program(), fe.ast_body());
   EXPECT_THAT(body_str, HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_1
diff --git a/src/reader/spirv/function_misc_test.cc b/src/reader/spirv/function_misc_test.cc
index 2558e49..978b1b6 100644
--- a/src/reader/spirv/function_misc_test.cc
+++ b/src/reader/spirv/function_misc_test.cc
@@ -68,7 +68,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_11
@@ -108,7 +108,7 @@
       ScalarConstructor[not set]{0.000000}
     }
   }
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTestMiscInstruction, OpUndef_InFunction_Vector) {
@@ -129,7 +129,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_11
@@ -171,7 +171,7 @@
       }
     }
   }
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTestMiscInstruction, OpUndef_InFunction_Matrix) {
@@ -190,7 +190,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_11
@@ -212,7 +212,7 @@
       }
     }
   }
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTestMiscInstruction, OpUndef_InFunction_Array) {
@@ -232,7 +232,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_11
@@ -246,7 +246,7 @@
       }
     }
   }
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTestMiscInstruction, OpUndef_InFunction_Struct) {
@@ -265,7 +265,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   VariableConst{
     x_11
@@ -281,7 +281,7 @@
       }
     }
   }
-})")) << ToString(p->get_module(), fe.ast_body());
+})")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTestMiscInstruction, OpNop) {
@@ -297,8 +297,8 @@
       << p->error() << assembly;
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), Eq(R"(Return{}
-)")) << ToString(p->get_module(), fe.ast_body());
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), Eq(R"(Return{}
+)")) << ToString(p->get_program(), fe.ast_body());
 }
 
 // Test swizzle generation.
@@ -329,7 +329,7 @@
     ASSERT_NE(result, nullptr);
     std::ostringstream ss;
     result->to_str(ss, 0);
-    auto str = Demangler().Demangle(p->get_module(), ss.str());
+    auto str = Demangler().Demangle(p->get_program(), ss.str());
     EXPECT_THAT(str, Eq(GetParam().expected_expr));
   } else {
     EXPECT_EQ(result, nullptr);
diff --git a/src/reader/spirv/function_var_test.cc b/src/reader/spirv/function_var_test.cc
index 96fab37..9707955 100644
--- a/src/reader/spirv/function_var_test.cc
+++ b/src/reader/spirv/function_var_test.cc
@@ -91,7 +91,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitFunctionVariables());
 
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   Variable{
     x_1
@@ -130,7 +130,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitFunctionVariables());
 
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   Variable{
     a
@@ -169,7 +169,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitFunctionVariables());
 
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   Variable{
     a
@@ -211,7 +211,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitFunctionVariables());
 
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   Variable{
     a
@@ -285,7 +285,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitFunctionVariables());
 
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   Variable{
     a
@@ -345,7 +345,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitFunctionVariables());
 
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   Variable{
     x_200
@@ -360,7 +360,7 @@
     }
   }
 }
-)")) << ToString(p->get_module(), fe.ast_body());
+)")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTest, EmitFunctionVariables_MatrixInitializer) {
@@ -384,7 +384,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitFunctionVariables());
 
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   Variable{
     x_200
@@ -431,7 +431,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitFunctionVariables());
 
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   Variable{
     x_200
@@ -446,7 +446,7 @@
     }
   }
 }
-)")) << ToString(p->get_module(), fe.ast_body());
+)")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTest, EmitFunctionVariables_ArrayInitializer_Alias) {
@@ -466,7 +466,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitFunctionVariables());
 
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   Variable{
     x_200
@@ -481,7 +481,7 @@
     }
   }
 }
-)")) << ToString(p->get_module(), fe.ast_body());
+)")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTest, EmitFunctionVariables_ArrayInitializer_Null) {
@@ -500,7 +500,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitFunctionVariables());
 
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   Variable{
     x_200
@@ -515,7 +515,7 @@
     }
   }
 }
-)")) << ToString(p->get_module(), fe.ast_body());
+)")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTest, EmitFunctionVariables_ArrayInitializer_Alias_Null) {
@@ -535,7 +535,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitFunctionVariables());
 
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   Variable{
     x_200
@@ -550,7 +550,7 @@
     }
   }
 }
-)")) << ToString(p->get_module(), fe.ast_body());
+)")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTest, EmitFunctionVariables_StructInitializer) {
@@ -570,7 +570,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitFunctionVariables());
 
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   Variable{
     x_200
@@ -590,7 +590,7 @@
     }
   }
 }
-)")) << ToString(p->get_module(), fe.ast_body());
+)")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTest, EmitFunctionVariables_StructInitializer_Null) {
@@ -610,7 +610,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitFunctionVariables());
 
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()),
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()),
               HasSubstr(R"(VariableDeclStatement{
   Variable{
     x_200
@@ -630,7 +630,7 @@
     }
   }
 }
-)")) << ToString(p->get_module(), fe.ast_body());
+)")) << ToString(p->get_program(), fe.ast_body());
 }
 
 TEST_F(SpvParserTest,
@@ -655,7 +655,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect =
       R"(VariableDeclStatement{
   Variable{
@@ -703,7 +703,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(VariableDeclStatement{
   Variable{
     x_25
@@ -775,7 +775,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(VariableDeclStatement{
   Variable{
     x_25
@@ -874,7 +874,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Assignment{
   Identifier[not set]{x_1}
   ScalarConstructor[not set]{0}
@@ -992,7 +992,7 @@
 
   // We don't hoist x_1 into its own mutable variable. It is emitted as
   // a const definition.
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(VariableDeclStatement{
   VariableConst{
     x_1
@@ -1077,7 +1077,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(If{
   (
     ScalarConstructor[not set]{true}
@@ -1164,7 +1164,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(If{
   (
     ScalarConstructor[not set]{true}
@@ -1247,7 +1247,7 @@
 
   // We don't hoist x_1 into its own mutable variable. It is emitted as
   // a const definition.
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(VariableDeclStatement{
   VariableConst{
     x_1
@@ -1321,7 +1321,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Loop{
   VariableDeclStatement{
     Variable{
@@ -1465,7 +1465,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(Loop{
   VariableDeclStatement{
     Variable{
@@ -1623,7 +1623,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(VariableDeclStatement{
   VariableConst{
     x_101
@@ -1792,7 +1792,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(VariableDeclStatement{
   VariableConst{
     x_101
@@ -1914,7 +1914,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(VariableDeclStatement{
   VariableConst{
     x_101
@@ -2022,7 +2022,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
 
-  auto got = ToString(p->get_module(), fe.ast_body());
+  auto got = ToString(p->get_program(), fe.ast_body());
   auto* expect = R"(VariableDeclStatement{
   Variable{
     x_101_phi
diff --git a/src/reader/spirv/parser.cc b/src/reader/spirv/parser.cc
index de8078a..3fc7710 100644
--- a/src/reader/spirv/parser.cc
+++ b/src/reader/spirv/parser.cc
@@ -38,8 +38,8 @@
   return result;
 }
 
-ast::Module Parser::module() {
-  return impl_->module();
+Program Parser::program() {
+  return impl_->program();
 }
 
 }  // namespace spirv
diff --git a/src/reader/spirv/parser.h b/src/reader/spirv/parser.h
index 0ace60c..842ccbc 100644
--- a/src/reader/spirv/parser.h
+++ b/src/reader/spirv/parser.h
@@ -40,8 +40,8 @@
   /// @returns true if the parse was successful, false otherwise.
   bool Parse() override;
 
-  /// @returns the module. The module in the parser will be reset after this.
-  ast::Module module() override;
+  /// @returns the program. The program in the parser will be reset after this.
+  Program program() override;
 
  private:
   std::unique_ptr<ParserImpl> impl_;
diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc
index 5a3a1d9..1e99926 100644
--- a/src/reader/spirv/parser_impl.cc
+++ b/src/reader/spirv/parser_impl.cc
@@ -255,7 +255,7 @@
     : Reader(),
       spv_binary_(spv_binary),
       fail_stream_(&success_, &errors_),
-      bool_type_(ast_module_.create<type::Bool>()),
+      bool_type_(program_.create<type::Bool>()),
       namer_(fail_stream_),
       enum_converter_(fail_stream_),
       tools_context_(kInputEnv) {
@@ -307,10 +307,10 @@
   return success_;
 }
 
-ast::Module ParserImpl::module() {
+Program ParserImpl::program() {
   // TODO(dneto): Should we clear out spv_binary_ here, to reduce
   // memory usage?
-  return std::move(ast_module_);
+  return std::move(program_);
 }
 
 type::Type* ParserImpl::ConvertType(uint32_t type_id) {
@@ -344,7 +344,7 @@
 
   switch (spirv_type->kind()) {
     case spvtools::opt::analysis::Type::kVoid:
-      return save(ast_module_.create<type::Void>());
+      return save(program_.create<type::Void>());
     case spvtools::opt::analysis::Type::kBool:
       return save(bool_type_);
     case spvtools::opt::analysis::Type::kInteger:
@@ -374,7 +374,7 @@
     case spvtools::opt::analysis::Type::kImage:
       // Fake it for sampler and texture types.  These are handled in an
       // entirely different way.
-      return save(ast_module_.create<type::Void>());
+      return save(program_.create<type::Void>());
     default:
       break;
   }
@@ -713,8 +713,8 @@
 type::Type* ParserImpl::ConvertType(
     const spvtools::opt::analysis::Integer* int_ty) {
   if (int_ty->width() == 32) {
-    type::Type* signed_ty = ast_module_.create<type::I32>();
-    type::Type* unsigned_ty = ast_module_.create<type::U32>();
+    type::Type* signed_ty = program_.create<type::I32>();
+    type::Type* unsigned_ty = program_.create<type::U32>();
     signed_type_for_[unsigned_ty] = signed_ty;
     unsigned_type_for_[signed_ty] = unsigned_ty;
     return int_ty->IsSigned() ? signed_ty : unsigned_ty;
@@ -726,7 +726,7 @@
 type::Type* ParserImpl::ConvertType(
     const spvtools::opt::analysis::Float* float_ty) {
   if (float_ty->width() == 32) {
-    return ast_module_.create<type::F32>();
+    return program_.create<type::F32>();
   }
   Fail() << "unhandled float width: " << float_ty->width();
   return nullptr;
@@ -739,16 +739,16 @@
   if (ast_elem_ty == nullptr) {
     return nullptr;
   }
-  auto* this_ty = ast_module_.create<type::Vector>(ast_elem_ty, num_elem);
+  auto* this_ty = program_.create<type::Vector>(ast_elem_ty, num_elem);
   // Generate the opposite-signedness vector type, if this type is integral.
   if (unsigned_type_for_.count(ast_elem_ty)) {
-    auto* other_ty = ast_module_.create<type::Vector>(
+    auto* other_ty = program_.create<type::Vector>(
         unsigned_type_for_[ast_elem_ty], num_elem);
     signed_type_for_[other_ty] = this_ty;
     unsigned_type_for_[this_ty] = other_ty;
   } else if (signed_type_for_.count(ast_elem_ty)) {
-    auto* other_ty = ast_module_.create<type::Vector>(
-        signed_type_for_[ast_elem_ty], num_elem);
+    auto* other_ty =
+        program_.create<type::Vector>(signed_type_for_[ast_elem_ty], num_elem);
     unsigned_type_for_[other_ty] = this_ty;
     signed_type_for_[this_ty] = other_ty;
   }
@@ -765,7 +765,7 @@
   if (ast_scalar_ty == nullptr) {
     return nullptr;
   }
-  return ast_module_.create<type::Matrix>(ast_scalar_ty, num_rows, num_columns);
+  return program_.create<type::Matrix>(ast_scalar_ty, num_rows, num_columns);
 }
 
 type::Type* ParserImpl::ConvertType(
@@ -947,7 +947,7 @@
     }
     const auto member_name = namer_.GetMemberName(type_id, member_index);
     auto* ast_struct_member = create<ast::StructMember>(
-        Source{}, ast_module_.RegisterSymbol(member_name), ast_member_ty,
+        Source{}, program_.RegisterSymbol(member_name), ast_member_ty,
         std::move(ast_member_decorations));
     ast_members.push_back(ast_struct_member);
   }
@@ -963,13 +963,13 @@
   namer_.SuggestSanitizedName(type_id, "S");
 
   auto name = namer_.GetName(type_id);
-  auto* result = ast_module_.create<type::Struct>(
-      ast_module_.RegisterSymbol(name), ast_struct);
+  auto* result =
+      program_.create<type::Struct>(program_.RegisterSymbol(name), ast_struct);
   id_to_type_[type_id] = result;
   if (num_non_writable_members == members.size()) {
     read_only_struct_types_.insert(result);
   }
-  ast_module_.AddConstructedType(result);
+  program_.AddConstructedType(result);
   return result;
 }
 
@@ -1003,7 +1003,7 @@
     ast_storage_class = ast::StorageClass::kStorage;
     remap_buffer_block_type_.insert(type_id);
   }
-  return ast_module_.create<type::Pointer>(ast_elem_ty, ast_storage_class);
+  return program_.create<type::Pointer>(ast_elem_ty, ast_storage_class);
 }
 
 bool ParserImpl::RegisterTypes() {
@@ -1091,7 +1091,7 @@
           MakeVariable(inst.result_id(), ast::StorageClass::kNone, ast_type,
                        true, ast_expr, std::move(spec_id_decos));
       if (ast_var) {
-        ast_module_.AddGlobalVariable(ast_var);
+        program_.AddGlobalVariable(ast_var);
         scalar_spec_constants_.insert(inst.result_id());
       }
     }
@@ -1129,11 +1129,11 @@
     return;
   }
   const auto name = namer_.GetName(type_id);
-  auto* ast_alias_type = ast_module_.create<type::Alias>(
-      ast_module_.RegisterSymbol(name), ast_underlying_type);
+  auto* ast_alias_type = program_.create<type::Alias>(
+      program_.RegisterSymbol(name), ast_underlying_type);
   // Record this new alias as the AST type for this SPIR-V ID.
   id_to_type_[type_id] = ast_alias_type;
-  ast_module_.AddConstructedType(ast_alias_type);
+  program_.AddConstructedType(ast_alias_type);
 }
 
 bool ParserImpl::EmitModuleScopeVariables() {
@@ -1209,7 +1209,7 @@
                      ast_constructor, ast::VariableDecorationList{});
     // TODO(dneto): initializers (a.k.a. constructor expression)
     if (ast_var) {
-      ast_module_.AddGlobalVariable(ast_var);
+      program_.AddGlobalVariable(ast_var);
     }
   }
 
@@ -1226,7 +1226,7 @@
             create<ast::BuiltinDecoration>(Source{}, ast::Builtin::kPosition),
         });
 
-    ast_module_.AddGlobalVariable(var);
+    program_.AddGlobalVariable(var);
   }
   return success_;
 }
@@ -1248,7 +1248,7 @@
     auto access = read_only_struct_types_.count(type)
                       ? ast::AccessControl::kReadOnly
                       : ast::AccessControl::kReadWrite;
-    type = ast_module_.create<type::AccessControl>(access, type);
+    type = program_.create<type::AccessControl>(access, type);
   }
 
   for (auto& deco : GetDecorationsFor(id)) {
@@ -1306,13 +1306,13 @@
   }
 
   std::string name = namer_.Name(id);
-  return create<ast::Variable>(Source{},                          // source
-                               ast_module_.RegisterSymbol(name),  // symbol
-                               sc,            // storage_class
-                               type,          // type
-                               is_const,      // is_const
-                               constructor,   // constructor
-                               decorations);  // decorations
+  return create<ast::Variable>(Source{},                       // source
+                               program_.RegisterSymbol(name),  // symbol
+                               sc,                             // storage_class
+                               type,                           // type
+                               is_const,                       // is_const
+                               constructor,                    // constructor
+                               decorations);                   // decorations
 }
 
 TypedExpression ParserImpl::MakeConstantExpression(uint32_t id) {
@@ -1451,7 +1451,7 @@
   if (const auto* mat_ty = type->As<type::Matrix>()) {
     // Matrix components are columns
     auto* column_ty =
-        ast_module_.create<type::Vector>(mat_ty->type(), mat_ty->rows());
+        program_.create<type::Vector>(mat_ty->type(), mat_ty->rows());
     ast::ExpressionList ast_components;
     for (size_t i = 0; i < mat_ty->columns(); ++i) {
       ast_components.emplace_back(MakeNullValue(column_ty));
@@ -1546,14 +1546,14 @@
   if (other == nullptr) {
     Fail() << "no type provided";
   }
-  auto* i32 = ast_module_.create<type::I32>();
+  auto* i32 = program_.create<type::I32>();
   if (other->Is<type::F32>() || other->Is<type::U32>() ||
       other->Is<type::I32>()) {
     return i32;
   }
   auto* vec_ty = other->As<type::Vector>();
   if (vec_ty) {
-    return ast_module_.create<type::Vector>(i32, vec_ty->size());
+    return program_.create<type::Vector>(i32, vec_ty->size());
   }
   Fail() << "required numeric scalar or vector, but got " << other->type_name();
   return nullptr;
@@ -1564,14 +1564,14 @@
     Fail() << "no type provided";
     return nullptr;
   }
-  auto* u32 = ast_module_.create<type::U32>();
+  auto* u32 = program_.create<type::U32>();
   if (other->Is<type::F32>() || other->Is<type::U32>() ||
       other->Is<type::I32>()) {
     return u32;
   }
   auto* vec_ty = other->As<type::Vector>();
   if (vec_ty) {
-    return ast_module_.create<type::Vector>(u32, vec_ty->size());
+    return program_.create<type::Vector>(u32, vec_ty->size());
   }
   Fail() << "required numeric scalar or vector, but got " << other->type_name();
   return nullptr;
@@ -1845,7 +1845,7 @@
   // Construct the Tint handle type.
   type::Type* ast_store_type = nullptr;
   if (usage.IsSampler()) {
-    ast_store_type = ast_module_.create<type::Sampler>(
+    ast_store_type = program_.create<type::Sampler>(
         usage.IsComparisonSampler() ? type::SamplerKind::kComparisonSampler
                                     : type::SamplerKind::kSampler);
   } else if (usage.IsTexture()) {
@@ -1876,13 +1876,13 @@
       // OpImage variable with an OpImage*Dref* instruction.  In WGSL we must
       // treat that as a depth texture.
       if (image_type->depth() || usage.IsDepthTexture()) {
-        ast_store_type = ast_module_.create<type::DepthTexture>(dim);
+        ast_store_type = program_.create<type::DepthTexture>(dim);
       } else if (image_type->is_multisampled()) {
         // Multisampled textures are never depth textures.
-        ast_store_type = ast_module_.create<type::MultisampledTexture>(
+        ast_store_type = program_.create<type::MultisampledTexture>(
             dim, ast_sampled_component_type);
       } else {
-        ast_store_type = ast_module_.create<type::SampledTexture>(
+        ast_store_type = program_.create<type::SampledTexture>(
             dim, ast_sampled_component_type);
       }
     } else {
@@ -1893,8 +1893,8 @@
       if (format == type::ImageFormat::kNone) {
         return nullptr;
       }
-      ast_store_type = ast_module_.create<type::AccessControl>(
-          access, ast_module_.create<type::StorageTexture>(dim, format));
+      ast_store_type = program_.create<type::AccessControl>(
+          access, program_.create<type::StorageTexture>(dim, format));
     }
   } else {
     Fail() << "unsupported: UniformConstant variable is not a recognized "
@@ -1904,7 +1904,7 @@
   }
 
   // Form the pointer type.
-  auto* result = ast_module_.create<type::Pointer>(
+  auto* result = program_.create<type::Pointer>(
       ast_store_type, ast::StorageClass::kUniformConstant);
   // Remember it for later.
   handle_type_[&var] = result;
@@ -1922,7 +1922,7 @@
     case type::ImageFormat::kRg32Uint:
     case type::ImageFormat::kRgba16Uint:
     case type::ImageFormat::kRgba32Uint:
-      return ast_module_.create<type::U32>();
+      return program_.create<type::U32>();
 
     case type::ImageFormat::kR8Sint:
     case type::ImageFormat::kR16Sint:
@@ -1933,7 +1933,7 @@
     case type::ImageFormat::kRg32Sint:
     case type::ImageFormat::kRgba16Sint:
     case type::ImageFormat::kRgba32Sint:
-      return ast_module_.create<type::I32>();
+      return program_.create<type::I32>();
 
     case type::ImageFormat::kR8Unorm:
     case type::ImageFormat::kRg8Unorm:
@@ -1952,7 +1952,7 @@
     case type::ImageFormat::kRg32Float:
     case type::ImageFormat::kRgba16Float:
     case type::ImageFormat::kRgba32Float:
-      return ast_module_.create<type::F32>();
+      return program_.create<type::F32>();
     default:
       break;
   }
@@ -1992,7 +1992,7 @@
     case type::ImageFormat::kRg8Uint:
     case type::ImageFormat::kRg8Unorm:
       // Two channels
-      return ast_module_.create<type::Vector>(component_type, 2);
+      return program_.create<type::Vector>(component_type, 2);
 
     case type::ImageFormat::kBgra8Unorm:
     case type::ImageFormat::kBgra8UnormSrgb:
@@ -2009,7 +2009,7 @@
     case type::ImageFormat::kRgba8Unorm:
     case type::ImageFormat::kRgba8UnormSrgb:
       // Four channels
-      return ast_module_.create<type::Vector>(component_type, 4);
+      return program_.create<type::Vector>(component_type, 4);
 
     default:
       break;
diff --git a/src/reader/spirv/parser_impl.h b/src/reader/spirv/parser_impl.h
index bc85862..c3cee04 100644
--- a/src/reader/spirv/parser_impl.h
+++ b/src/reader/spirv/parser_impl.h
@@ -32,8 +32,8 @@
 #include "source/opt/types.h"
 #include "spirv-tools/libspirv.hpp"
 #include "src/ast/expression.h"
-#include "src/ast/module.h"
 #include "src/ast/struct_member_decoration.h"
+#include "src/program.h"
 #include "src/reader/reader.h"
 #include "src/reader/spirv/entry_point_info.h"
 #include "src/reader/spirv/enum_converter.h"
@@ -95,12 +95,12 @@
   /// @returns true if the parse was successful, false otherwise.
   bool Parse() override;
 
-  /// @returns the module. The module in the parser will be reset after this.
-  ast::Module module() override;
+  /// @returns the program. The program in the parser will be reset after this.
+  Program program() override;
 
-  /// Returns a pointer to the module, without resetting it.
-  /// @returns the module
-  ast::Module& get_module() { return ast_module_; }
+  /// Returns a reference to the program, without resetting it.
+  /// @returns the program
+  Program& get_program() { return program_; }
 
   /// Logs failure, ands return a failure stream to accumulate diagnostic
   /// messages. By convention, a failure should only be logged along with
@@ -118,14 +118,14 @@
   const std::string error() { return errors_.str(); }
 
   /// Builds an internal representation of the SPIR-V binary,
-  /// and parses it into a Tint AST module.  Diagnostics are emitted
+  /// and parses it into a Tint program.  Diagnostics are emitted
   /// to the error stream.
   /// @returns true if it was successful.
   bool BuildAndParseInternalModule() {
     return BuildInternalModule() && ParseInternalModule();
   }
   /// Builds an internal representation of the SPIR-V binary,
-  /// and parses the module, except functions, into a Tint AST module.
+  /// and parses the module, except functions, into a Tint program.
   /// Diagnostics are emitted to the error stream.
   /// @returns true if it was successful.
   bool BuildAndParseInternalModuleExceptFunctions() {
@@ -524,20 +524,20 @@
   bool ParseArrayDecorations(const spvtools::opt::analysis::Type* spv_type,
                              ast::ArrayDecorationList* decorations);
 
-  /// Creates a new `ast::Node` owned by the Module. When the Module is
+  /// Creates a new `ast::Node` owned by the Program. When the Program is
   /// destructed, the `ast::Node` will also be destructed.
   /// @param args the arguments to pass to the type constructor
   /// @returns the node pointer
   template <typename T, typename... ARGS>
   T* create(ARGS&&... args) {
-    return ast_module_.create<T>(std::forward<ARGS>(args)...);
+    return program_.create<T>(std::forward<ARGS>(args)...);
   }
 
   // The SPIR-V binary we're parsing
   std::vector<uint32_t> spv_binary_;
 
   // The resulting module in Tint AST form.
-  ast::Module ast_module_;
+  Program program_;
 
   // Is the parse successful?
   bool success_ = true;
diff --git a/src/reader/spirv/parser_impl_convert_type_test.cc b/src/reader/spirv/parser_impl_convert_type_test.cc
index cc871c0..f76b004 100644
--- a/src/reader/spirv/parser_impl_convert_type_test.cc
+++ b/src/reader/spirv/parser_impl_convert_type_test.cc
@@ -566,7 +566,7 @@
   EXPECT_TRUE(type->Is<type::Struct>());
   std::stringstream ss;
   type->As<type::Struct>()->impl()->to_str(ss, 0);
-  EXPECT_THAT(Demangler().Demangle(p->get_module(), ss.str()), Eq(R"(Struct{
+  EXPECT_THAT(Demangler().Demangle(p->get_program(), ss.str()), Eq(R"(Struct{
   StructMember{field0: __u32}
   StructMember{field1: __f32}
 }
@@ -587,7 +587,7 @@
   EXPECT_TRUE(type->Is<type::Struct>());
   std::stringstream ss;
   type->As<type::Struct>()->impl()->to_str(ss, 0);
-  EXPECT_THAT(Demangler().Demangle(p->get_module(), ss.str()), Eq(R"(Struct{
+  EXPECT_THAT(Demangler().Demangle(p->get_program(), ss.str()), Eq(R"(Struct{
   [[block]]
   StructMember{field0: __u32}
 }
@@ -612,7 +612,7 @@
   EXPECT_TRUE(type->Is<type::Struct>());
   std::stringstream ss;
   type->As<type::Struct>()->impl()->to_str(ss, 0);
-  EXPECT_THAT(Demangler().Demangle(p->get_module(), ss.str()), Eq(R"(Struct{
+  EXPECT_THAT(Demangler().Demangle(p->get_program(), ss.str()), Eq(R"(Struct{
   StructMember{[[ offset 0 ]] field0: __f32}
   StructMember{[[ offset 8 ]] field1: __vec_2__f32}
   StructMember{[[ offset 16 ]] field2: __mat_2_2__f32}
diff --git a/src/reader/spirv/parser_impl_function_decl_test.cc b/src/reader/spirv/parser_impl_function_decl_test.cc
index ef85635..5c6f1d5 100644
--- a/src/reader/spirv/parser_impl_function_decl_test.cc
+++ b/src/reader/spirv/parser_impl_function_decl_test.cc
@@ -53,8 +53,8 @@
   auto p = parser(test::Assemble(CommonTypes()));
   EXPECT_TRUE(p->BuildAndParseInternalModule());
   EXPECT_TRUE(p->error().empty());
-  const auto module_ast = p->get_module().to_str();
-  EXPECT_THAT(module_ast, Not(HasSubstr("Function{")));
+  const auto program_ast = p->get_program().to_str();
+  EXPECT_THAT(program_ast, Not(HasSubstr("Function{")));
 }
 
 TEST_F(SpvParserTest, EmitFunctions_FunctionWithoutBody) {
@@ -64,8 +64,8 @@
   )"));
   EXPECT_TRUE(p->BuildAndParseInternalModule());
   EXPECT_TRUE(p->error().empty());
-  const auto module_ast = p->get_module().to_str();
-  EXPECT_THAT(module_ast, Not(HasSubstr("Function{")));
+  const auto program_ast = p->get_program().to_str();
+  EXPECT_THAT(program_ast, Not(HasSubstr("Function{")));
 }
 
 TEST_F(SpvParserTest, EmitFunctions_Function_EntryPoint_Vertex) {
@@ -79,10 +79,10 @@
   auto p = parser(test::Assemble(input));
   ASSERT_TRUE(p->BuildAndParseInternalModule());
   ASSERT_TRUE(p->error().empty()) << p->error();
-  const auto module_ast = p->get_module().to_str();
-  EXPECT_THAT(module_ast, HasSubstr(R"(
-  Function )" + p->get_module().GetSymbol("main").to_str() +
-                                    R"( -> __void
+  const auto program_ast = p->get_program().to_str();
+  EXPECT_THAT(program_ast, HasSubstr(R"(
+  Function )" + p->get_program().GetSymbol("main").to_str() +
+                                     R"( -> __void
   StageDecoration{vertex}
   ()
   {)"));
@@ -99,10 +99,10 @@
   auto p = parser(test::Assemble(input));
   ASSERT_TRUE(p->BuildAndParseInternalModule());
   ASSERT_TRUE(p->error().empty()) << p->error();
-  const auto module_ast = p->get_module().to_str();
-  EXPECT_THAT(module_ast, HasSubstr(R"(
-  Function )" + p->get_module().GetSymbol("main").to_str() +
-                                    R"( -> __void
+  const auto program_ast = p->get_program().to_str();
+  EXPECT_THAT(program_ast, HasSubstr(R"(
+  Function )" + p->get_program().GetSymbol("main").to_str() +
+                                     R"( -> __void
   StageDecoration{fragment}
   ()
   {)"));
@@ -119,10 +119,10 @@
   auto p = parser(test::Assemble(input));
   ASSERT_TRUE(p->BuildAndParseInternalModule());
   ASSERT_TRUE(p->error().empty()) << p->error();
-  const auto module_ast = p->get_module().to_str();
-  EXPECT_THAT(module_ast, HasSubstr(R"(
-  Function )" + p->get_module().GetSymbol("main").to_str() +
-                                    R"( -> __void
+  const auto program_ast = p->get_program().to_str();
+  EXPECT_THAT(program_ast, HasSubstr(R"(
+  Function )" + p->get_program().GetSymbol("main").to_str() +
+                                     R"( -> __void
   StageDecoration{compute}
   ()
   {)"));
@@ -141,16 +141,16 @@
   auto p = parser(test::Assemble(input));
   ASSERT_TRUE(p->BuildAndParseInternalModule());
   ASSERT_TRUE(p->error().empty()) << p->error();
-  const auto module_ast = p->get_module().to_str();
-  EXPECT_THAT(module_ast, HasSubstr(R"(
-  Function )" + p->get_module().GetSymbol("frag_main").to_str() +
-                                    R"( -> __void
+  const auto program_ast = p->get_program().to_str();
+  EXPECT_THAT(program_ast, HasSubstr(R"(
+  Function )" + p->get_program().GetSymbol("frag_main").to_str() +
+                                     R"( -> __void
   StageDecoration{fragment}
   ()
   {)"));
-  EXPECT_THAT(module_ast, HasSubstr(R"(
-  Function )" + p->get_module().GetSymbol("comp_main").to_str() +
-                                    R"( -> __void
+  EXPECT_THAT(program_ast, HasSubstr(R"(
+  Function )" + p->get_program().GetSymbol("comp_main").to_str() +
+                                     R"( -> __void
   StageDecoration{compute}
   ()
   {)"));
@@ -165,10 +165,10 @@
   )"));
   EXPECT_TRUE(p->BuildAndParseInternalModule());
   EXPECT_TRUE(p->error().empty());
-  const auto module_ast = p->get_module().to_str();
-  EXPECT_THAT(module_ast, HasSubstr(R"(
-  Function )" + p->get_module().GetSymbol("main").to_str() +
-                                    R"( -> __void
+  const auto program_ast = p->get_program().to_str();
+  EXPECT_THAT(program_ast, HasSubstr(R"(
+  Function )" + p->get_program().GetSymbol("main").to_str() +
+                                     R"( -> __void
   ()
   {)"));
 }
@@ -199,9 +199,9 @@
   )"));
   EXPECT_TRUE(p->BuildAndParseInternalModule());
   EXPECT_TRUE(p->error().empty());
-  const auto module_ast =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
-  EXPECT_THAT(module_ast, HasSubstr(R"(
+  const auto program_ast =
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
+  EXPECT_THAT(program_ast, HasSubstr(R"(
   Function leaf -> __u32
   ()
   {
@@ -253,7 +253,7 @@
     }
     Return{}
   }
-})")) << module_ast;
+})")) << program_ast;
 }
 
 TEST_F(SpvParserTest, EmitFunctions_NonVoidResultType) {
@@ -267,9 +267,9 @@
   )"));
   EXPECT_TRUE(p->BuildAndParseInternalModule());
   EXPECT_TRUE(p->error().empty());
-  const auto module_ast =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
-  EXPECT_THAT(module_ast, HasSubstr(R"(
+  const auto program_ast =
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
+  EXPECT_THAT(program_ast, HasSubstr(R"(
   Function ret_float -> __f32
   ()
   {
@@ -279,7 +279,7 @@
       }
     }
   })"))
-      << module_ast;
+      << program_ast;
 }
 
 TEST_F(SpvParserTest, EmitFunctions_MixedParamTypes) {
@@ -297,9 +297,9 @@
   )"));
   EXPECT_TRUE(p->BuildAndParseInternalModule());
   EXPECT_TRUE(p->error().empty());
-  const auto module_ast =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
-  EXPECT_THAT(module_ast, HasSubstr(R"(
+  const auto program_ast =
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
+  EXPECT_THAT(program_ast, HasSubstr(R"(
   Function mixed_params -> __void
   (
     VariableConst{
@@ -337,9 +337,9 @@
   )"));
   EXPECT_TRUE(p->BuildAndParseInternalModule());
   EXPECT_TRUE(p->error().empty());
-  const auto module_ast =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
-  EXPECT_THAT(module_ast, HasSubstr(R"(
+  const auto program_ast =
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
+  EXPECT_THAT(program_ast, HasSubstr(R"(
   Function mixed_params -> __void
   (
     VariableConst{
@@ -361,7 +361,7 @@
   {
     Return{}
   })"))
-      << module_ast;
+      << program_ast;
 }
 
 }  // namespace
diff --git a/src/reader/spirv/parser_impl_handle_test.cc b/src/reader/spirv/parser_impl_handle_test.cc
index 8844c6c..3bdd6e1 100644
--- a/src/reader/spirv/parser_impl_handle_test.cc
+++ b/src/reader/spirv/parser_impl_handle_test.cc
@@ -1129,9 +1129,9 @@
   auto p = parser(test::Assemble(assembly));
   ASSERT_TRUE(p->BuildAndParseInternalModule()) << p->error() << assembly;
   EXPECT_TRUE(p->error().empty()) << p->error();
-  const auto module =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
-  EXPECT_THAT(module, HasSubstr(GetParam().var_decl)) << module;
+  const auto program =
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
+  EXPECT_THAT(program, HasSubstr(GetParam().var_decl)) << program;
 }
 
 INSTANTIATE_TEST_SUITE_P(Samplers,
@@ -1306,12 +1306,12 @@
   auto p = parser(test::Assemble(assembly));
   ASSERT_TRUE(p->BuildAndParseInternalModule()) << p->error() << assembly;
   EXPECT_TRUE(p->error().empty()) << p->error();
-  const auto module =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
-  EXPECT_THAT(module, HasSubstr(GetParam().var_decl))
-      << "DECLARATIONS ARE BAD " << module;
-  EXPECT_THAT(module, HasSubstr(GetParam().texture_builtin))
-      << "TEXTURE BUILTIN IS BAD " << module << assembly;
+  const auto program =
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
+  EXPECT_THAT(program, HasSubstr(GetParam().var_decl))
+      << "DECLARATIONS ARE BAD " << program;
+  EXPECT_THAT(program, HasSubstr(GetParam().texture_builtin))
+      << "TEXTURE BUILTIN IS BAD " << program << assembly;
 }
 
 // TODO(dneto): Test variable declaration and texture builtins provoked by
@@ -2556,12 +2556,12 @@
   auto p = parser(test::Assemble(assembly));
   ASSERT_TRUE(p->BuildAndParseInternalModule()) << p->error() << assembly;
   EXPECT_TRUE(p->error().empty()) << p->error();
-  const auto module =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
-  EXPECT_THAT(module, HasSubstr(GetParam().var_decl))
-      << "DECLARATIONS ARE BAD " << module;
-  EXPECT_THAT(module, HasSubstr(GetParam().texture_builtin))
-      << "TEXTURE BUILTIN IS BAD " << module << assembly;
+  const auto program =
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
+  EXPECT_THAT(program, HasSubstr(GetParam().var_decl))
+      << "DECLARATIONS ARE BAD " << program;
+  EXPECT_THAT(program, HasSubstr(GetParam().texture_builtin))
+      << "TEXTURE BUILTIN IS BAD " << program << assembly;
 }
 
 INSTANTIATE_TEST_SUITE_P(ImageWrite_OptionalParams,
@@ -3712,7 +3712,7 @@
       for (auto* expr : result) {
         ASSERT_NE(expr, nullptr);
         result_strings.push_back(
-            Demangler().Demangle(p->get_module(), expr->str()));
+            Demangler().Demangle(p->get_program(), expr->str()));
       }
       EXPECT_THAT(result_strings,
                   ::testing::ContainerEq(GetParam().expected_expressions));
diff --git a/src/reader/spirv/parser_impl_import_test.cc b/src/reader/spirv/parser_impl_import_test.cc
index cb01dff..a949cda 100644
--- a/src/reader/spirv/parser_impl_import_test.cc
+++ b/src/reader/spirv/parser_impl_import_test.cc
@@ -35,8 +35,8 @@
   auto p = parser(test::Assemble("%1 = OpTypeVoid"));
   EXPECT_TRUE(p->BuildAndParseInternalModule());
   EXPECT_TRUE(p->error().empty());
-  const auto module_ast = p->module().to_str();
-  EXPECT_THAT(module_ast, Not(HasSubstr("Import")));
+  const auto program_ast = p->program().to_str();
+  EXPECT_THAT(program_ast, Not(HasSubstr("Import")));
 }
 
 TEST_F(SpvParserTest, Import_ImportGlslStd450) {
diff --git a/src/reader/spirv/parser_impl_module_var_test.cc b/src/reader/spirv/parser_impl_module_var_test.cc
index aca14de..fd35169 100644
--- a/src/reader/spirv/parser_impl_module_var_test.cc
+++ b/src/reader/spirv/parser_impl_module_var_test.cc
@@ -70,8 +70,8 @@
   auto p = parser(test::Assemble(""));
   EXPECT_TRUE(p->BuildAndParseInternalModule());
   EXPECT_TRUE(p->error().empty());
-  const auto module_ast = p->module().to_str();
-  EXPECT_THAT(module_ast, Not(HasSubstr("Variable")));
+  const auto program_ast = p->program().to_str();
+  EXPECT_THAT(program_ast, Not(HasSubstr("Variable")));
 }
 
 TEST_F(SpvModuleScopeVarParserTest, BadStorageClass_NotAWebGPUStorageClass) {
@@ -144,7 +144,7 @@
   EXPECT_TRUE(p->BuildAndParseInternalModule());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
   Variable{
     x_52
@@ -164,7 +164,7 @@
   EXPECT_TRUE(p->BuildAndParseInternalModule());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
   Variable{
     the_counter
@@ -184,7 +184,7 @@
   EXPECT_TRUE(p->BuildAndParseInternalModule());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
   Variable{
     my_own_private_idaho
@@ -204,7 +204,7 @@
   EXPECT_TRUE(p->BuildAndParseInternalModule());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
   Variable{
     Decorations{
@@ -255,7 +255,7 @@
   EXPECT_EQ(position_info.storage_class, SpvStorageClassOutput);
   EXPECT_EQ(position_info.per_vertex_var_id, 1u);
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
   Variable{
     Decorations{
@@ -336,7 +336,7 @@
   EXPECT_TRUE(p->BuildAndParseInternalModule());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
     Assignment{
       Identifier[not set]{gl_Position}
@@ -390,7 +390,7 @@
   EXPECT_TRUE(p->BuildAndParseInternalModule());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
     Assignment{
       Identifier[not set]{gl_Position}
@@ -422,7 +422,7 @@
   EXPECT_TRUE(p->BuildAndParseInternalModule());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
     Assignment{
       MemberAccessor[not set]{
@@ -454,7 +454,7 @@
   EXPECT_TRUE(p->BuildAndParseInternalModule());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
   {
     Assignment{
@@ -485,7 +485,7 @@
   EXPECT_TRUE(p->BuildAndParseInternalModule());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_EQ(module_str, R"(Module{
   Variable{
     Decorations{
@@ -542,7 +542,7 @@
   EXPECT_TRUE(p->BuildAndParseInternalModule());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_EQ(module_str, R"(Module{
   Variable{
     x_900
@@ -610,7 +610,7 @@
   EXPECT_TRUE(p->BuildAndParseInternalModule()) << p->error();
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_EQ(module_str, R"(Module{
   Variable{
     Decorations{
@@ -662,7 +662,7 @@
   EXPECT_TRUE(p->BuildAndParseInternalModule());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_EQ(module_str, R"(Module{
   Function x_500 -> __void
   ()
@@ -707,7 +707,7 @@
   EXPECT_TRUE(p->BuildAndParseInternalModule());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_EQ(module_str, R"(Module{
   Variable{
     x_900
@@ -744,7 +744,7 @@
   EXPECT_TRUE(p->BuildAndParseInternalModule()) << p->error();
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_EQ(module_str, R"(Module{
   Function x_500 -> __void
   ()
@@ -772,7 +772,7 @@
   EXPECT_TRUE(p->BuildAndParseInternalModule()) << p->error();
   EXPECT_TRUE(p->error().empty()) << p->error();
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_EQ(module_str, R"(Module{
   Function x_500 -> __void
   ()
@@ -877,7 +877,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(Variable{
     x_1
     private
@@ -935,7 +935,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(Variable{
     x_1
     private
@@ -985,7 +985,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(Variable{
     x_1
     private
@@ -1030,7 +1030,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(Variable{
     x_200
     private
@@ -1054,7 +1054,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(Variable{
     x_200
     private
@@ -1078,7 +1078,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(Variable{
     x_200
     private
@@ -1102,7 +1102,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(Variable{
     x_200
     private
@@ -1126,7 +1126,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(Variable{
     x_200
     private
@@ -1150,7 +1150,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(Variable{
     x_200
     private
@@ -1174,7 +1174,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(Variable{
     x_200
     private
@@ -1198,7 +1198,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(Variable{
     x_200
     private
@@ -1222,7 +1222,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(Variable{
     x_200
     private
@@ -1252,7 +1252,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(Variable{
     x_200
     private
@@ -1289,7 +1289,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(Variable{
     x_200
     private
@@ -1326,7 +1326,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(Variable{
     x_200
     private
@@ -1364,7 +1364,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(Variable{
     x_200
     private
@@ -1388,7 +1388,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(Variable{
     x_200
     private
@@ -1412,7 +1412,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(Variable{
     x_200
     private
@@ -1438,7 +1438,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(Variable{
     x_200
     private
@@ -1468,7 +1468,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(Variable{
     x_200
     private
@@ -1498,7 +1498,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(Variable{
     x_200
     private
@@ -1530,7 +1530,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
   Variable{
     Decorations{
@@ -1583,7 +1583,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
   Variable{
     Decorations{
@@ -1638,7 +1638,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
   Variable{
     Decorations{
@@ -1693,7 +1693,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
   S Struct{
     [[block]]
@@ -1725,7 +1725,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
   S Struct{
     [[block]]
@@ -1755,7 +1755,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
   S Struct{
     [[block]]
@@ -1805,7 +1805,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
   S Struct{
     [[block]]
@@ -1835,7 +1835,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
   S Struct{
     [[block]]
@@ -1868,7 +1868,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
   S Struct{
     [[block]]
@@ -1893,7 +1893,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
   VariableConst{
     Decorations{
@@ -1919,7 +1919,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
   VariableConst{
     Decorations{
@@ -1945,7 +1945,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
   VariableConst{
     Decorations{
@@ -1971,7 +1971,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
   VariableConst{
     Decorations{
@@ -1997,7 +1997,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
   VariableConst{
     Decorations{
@@ -2024,7 +2024,7 @@
   ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
   EXPECT_TRUE(p->error().empty());
   const auto module_str =
-      Demangler().Demangle(p->get_module(), p->get_module().to_str());
+      Demangler().Demangle(p->get_program(), p->get_program().to_str());
   EXPECT_THAT(module_str, HasSubstr(R"(
   VariableConst{
     myconst
@@ -2053,7 +2053,7 @@
   FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
   EXPECT_TRUE(fe.EmitBody()) << p->error();
   EXPECT_TRUE(p->error().empty());
-  EXPECT_THAT(ToString(p->get_module(), fe.ast_body()), HasSubstr(R"(
+  EXPECT_THAT(ToString(p->get_program(), fe.ast_body()), HasSubstr(R"(
   VariableConst{
     x_1
     none
@@ -2066,7 +2066,7 @@
       }
     }
   })"))
-      << ToString(p->get_module(), fe.ast_body());
+      << ToString(p->get_program(), fe.ast_body());
 }
 
 }  // namespace
diff --git a/src/reader/spirv/parser_impl_named_types_test.cc b/src/reader/spirv/parser_impl_named_types_test.cc
index 13f9af9..d1c46f9 100644
--- a/src/reader/spirv/parser_impl_named_types_test.cc
+++ b/src/reader/spirv/parser_impl_named_types_test.cc
@@ -18,14 +18,14 @@
 
 #include "gmock/gmock.h"
 #include "src/ast/struct.h"
-#include "src/type/array_type.h"
-#include "src/type/matrix_type.h"
-#include "src/type/struct_type.h"
-#include "src/type/vector_type.h"
 #include "src/demangler.h"
 #include "src/reader/spirv/parser_impl.h"
 #include "src/reader/spirv/parser_impl_test_helper.h"
 #include "src/reader/spirv/spirv_tools_helpers_test.h"
+#include "src/type/array_type.h"
+#include "src/type/matrix_type.h"
+#include "src/type/struct_type.h"
+#include "src/type/vector_type.h"
 
 namespace tint {
 namespace reader {
@@ -40,7 +40,7 @@
     %s = OpTypeStruct %uint %uint
   )"));
   EXPECT_TRUE(p->BuildAndParseInternalModule());
-  EXPECT_THAT(Demangler().Demangle(p->get_module(), p->get_module().to_str()),
+  EXPECT_THAT(Demangler().Demangle(p->get_program(), p->get_program().to_str()),
               HasSubstr("S Struct"));
 }
 
@@ -51,7 +51,7 @@
     %s = OpTypeStruct %uint %uint
   )"));
   EXPECT_TRUE(p->BuildAndParseInternalModule());
-  EXPECT_THAT(Demangler().Demangle(p->get_module(), p->get_module().to_str()),
+  EXPECT_THAT(Demangler().Demangle(p->get_program(), p->get_program().to_str()),
               HasSubstr("mystruct Struct"));
 }
 
@@ -62,7 +62,7 @@
     %s2 = OpTypeStruct %uint %uint
   )"));
   EXPECT_TRUE(p->BuildAndParseInternalModule()) << p->error();
-  EXPECT_THAT(Demangler().Demangle(p->get_module(), p->get_module().to_str()),
+  EXPECT_THAT(Demangler().Demangle(p->get_program(), p->get_program().to_str()),
               HasSubstr(R"(S Struct{
     StructMember{field0: __u32}
     StructMember{field1: __u32}
@@ -84,7 +84,7 @@
     %arr = OpTypeRuntimeArray %uint
   )"));
   EXPECT_TRUE(p->BuildAndParseInternalModule());
-  EXPECT_THAT(Demangler().Demangle(p->get_module(), p->get_module().to_str()),
+  EXPECT_THAT(Demangler().Demangle(p->get_program(), p->get_program().to_str()),
               HasSubstr("RTArr -> __array__u32_stride_8\n"));
 }
 
@@ -97,7 +97,7 @@
     %arr2 = OpTypeRuntimeArray %uint
   )"));
   EXPECT_TRUE(p->BuildAndParseInternalModule());
-  EXPECT_THAT(Demangler().Demangle(p->get_module(), p->get_module().to_str()),
+  EXPECT_THAT(Demangler().Demangle(p->get_program(), p->get_program().to_str()),
               HasSubstr("RTArr -> __array__u32_stride_8\n  RTArr_1 -> "
                         "__array__u32_stride_8\n"));
 }
@@ -110,7 +110,7 @@
     %arr = OpTypeRuntimeArray %uint
   )"));
   EXPECT_TRUE(p->BuildAndParseInternalModule());
-  EXPECT_THAT(Demangler().Demangle(p->get_module(), p->get_module().to_str()),
+  EXPECT_THAT(Demangler().Demangle(p->get_program(), p->get_program().to_str()),
               HasSubstr("myrtarr -> __array__u32_stride_8\n"));
 }
 
@@ -124,7 +124,7 @@
     %arr2 = OpTypeArray %uint %uint_5
   )"));
   EXPECT_TRUE(p->BuildAndParseInternalModule());
-  EXPECT_THAT(Demangler().Demangle(p->get_module(), p->get_module().to_str()),
+  EXPECT_THAT(Demangler().Demangle(p->get_program(), p->get_program().to_str()),
               HasSubstr("myarr -> __array__u32_5_stride_8"));
 }
 
@@ -138,7 +138,7 @@
     %arr2 = OpTypeArray %uint %uint_5
   )"));
   EXPECT_TRUE(p->BuildAndParseInternalModule());
-  EXPECT_THAT(Demangler().Demangle(p->get_module(), p->get_module().to_str()),
+  EXPECT_THAT(Demangler().Demangle(p->get_program(), p->get_program().to_str()),
               HasSubstr("Arr -> __array__u32_5_stride_8\n  Arr_1 -> "
                         "__array__u32_5_stride_8"));
 }
diff --git a/src/reader/spirv/parser_impl_test_helper.h b/src/reader/spirv/parser_impl_test_helper.h
index e8283c6..c296e87 100644
--- a/src/reader/spirv/parser_impl_test_helper.h
+++ b/src/reader/spirv/parser_impl_test_helper.h
@@ -58,16 +58,16 @@
 using SpvParserTest = SpvParserTestBase<::testing::Test>;
 
 /// Returns the string dump of a statement list.
-/// @param mod the module
+/// @param program the program
 /// @param stmts the statement list
 /// @returns the string dump of a statement list.
-inline std::string ToString(const ast::Module& mod,
+inline std::string ToString(const Program& program,
                             const ast::StatementList& stmts) {
   std::ostringstream outs;
   for (const auto* stmt : stmts) {
     stmt->to_str(outs, 0);
   }
-  return Demangler().Demangle(mod, outs.str());
+  return Demangler().Demangle(program, outs.str());
 }
 
 }  // namespace spirv
diff --git a/src/reader/wgsl/parser.cc b/src/reader/wgsl/parser.cc
index 9a16198..aec5b68 100644
--- a/src/reader/wgsl/parser.cc
+++ b/src/reader/wgsl/parser.cc
@@ -35,8 +35,8 @@
   return ret;
 }
 
-ast::Module Parser::module() {
-  return impl_->module();
+Program Parser::program() {
+  return impl_->program();
 }
 
 }  // namespace wgsl
diff --git a/src/reader/wgsl/parser.h b/src/reader/wgsl/parser.h
index 3aaca80..42da6bb 100644
--- a/src/reader/wgsl/parser.h
+++ b/src/reader/wgsl/parser.h
@@ -39,8 +39,8 @@
   /// @returns true if the parse was successful, false otherwise.
   bool Parse() override;
 
-  /// @returns the module. The module in the parser will be reset after this.
-  ast::Module module() override;
+  /// @returns the program. The program in the parser will be reset after this.
+  Program program() override;
 
  private:
   std::unique_ptr<ParserImpl> impl_;
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index 9521365..284d87d 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -293,7 +293,7 @@
     }
   }
 
-  assert(module_.IsValid());
+  assert(program_.IsValid());
 }
 
 // global_decl
@@ -323,7 +323,7 @@
       if (!expect("variable declaration", Token::Type::kSemicolon))
         return Failure::kErrored;
 
-      module_.AddGlobalVariable(gv.value);
+      program_.AddGlobalVariable(gv.value);
       return true;
     }
 
@@ -335,7 +335,7 @@
       if (!expect("constant declaration", Token::Type::kSemicolon))
         return Failure::kErrored;
 
-      module_.AddGlobalVariable(gc.value);
+      program_.AddGlobalVariable(gc.value);
       return true;
     }
 
@@ -347,7 +347,7 @@
       if (!expect("type alias", Token::Type::kSemicolon))
         return Failure::kErrored;
 
-      module_.AddConstructedType(ta.value);
+      program_.AddConstructedType(ta.value);
       return true;
     }
 
@@ -361,8 +361,8 @@
 
       auto* type = str.value;
       register_constructed(
-          module_.SymbolToName(type->As<type::Struct>()->symbol()), type);
-      module_.AddConstructedType(type);
+          program_.SymbolToName(type->As<type::Struct>()->symbol()), type);
+      program_.AddConstructedType(type);
       return true;
     }
 
@@ -378,7 +378,7 @@
   if (func.errored)
     errored = true;
   if (func.matched) {
-    module_.Functions().Add(func.value);
+    program_.Functions().Add(func.value);
     return true;
   }
 
@@ -435,8 +435,8 @@
     constructor = expr.value;
   }
 
-  return create<ast::Variable>(decl->source,                        // source
-                               module_.RegisterSymbol(decl->name),  // symbol
+  return create<ast::Variable>(decl->source,                         // source
+                               program_.RegisterSymbol(decl->name),  // symbol
                                decl->storage_class,          // storage_class
                                decl->type,                   // type
                                false,                        // is_const
@@ -463,8 +463,8 @@
   if (init.errored)
     return Failure::kErrored;
 
-  return create<ast::Variable>(decl->source,                        // source
-                               module_.RegisterSymbol(decl->name),  // symbol
+  return create<ast::Variable>(decl->source,                         // source
+                               program_.RegisterSymbol(decl->name),  // symbol
                                ast::StorageClass::kNone,        // storage_class
                                decl->type,                      // type
                                true,                            // is_const
@@ -514,7 +514,7 @@
     if (subtype.errored)
       return Failure::kErrored;
 
-    return module_.create<type::SampledTexture>(dim.value, subtype.value);
+    return program_.create<type::SampledTexture>(dim.value, subtype.value);
   }
 
   auto ms_dim = multisampled_texture_type();
@@ -525,8 +525,8 @@
     if (subtype.errored)
       return Failure::kErrored;
 
-    return module_.create<type::MultisampledTexture>(ms_dim.value,
-                                                     subtype.value);
+    return program_.create<type::MultisampledTexture>(ms_dim.value,
+                                                      subtype.value);
   }
 
   auto storage = storage_texture_type();
@@ -539,7 +539,7 @@
     if (format.errored)
       return Failure::kErrored;
 
-    return module_.create<type::StorageTexture>(storage.value, format.value);
+    return program_.create<type::StorageTexture>(storage.value, format.value);
   }
 
   // DEPRECATED
@@ -553,9 +553,9 @@
     if (format.errored)
       return Failure::kErrored;
 
-    return module_.create<type::AccessControl>(
+    return program_.create<type::AccessControl>(
         ac_storage->second,
-        module_.create<type::StorageTexture>(ac_storage->first, format.value));
+        program_.create<type::StorageTexture>(ac_storage->first, format.value));
   }
 
   return Failure::kNoMatch;
@@ -566,10 +566,11 @@
 //  | SAMPLER_COMPARISON
 Maybe<type::Type*> ParserImpl::sampler_type() {
   if (match(Token::Type::kSampler))
-    return module_.create<type::Sampler>(type::SamplerKind::kSampler);
+    return program_.create<type::Sampler>(type::SamplerKind::kSampler);
 
   if (match(Token::Type::kComparisonSampler))
-    return module_.create<type::Sampler>(type::SamplerKind::kComparisonSampler);
+    return program_.create<type::Sampler>(
+        type::SamplerKind::kComparisonSampler);
 
   return Failure::kNoMatch;
 }
@@ -714,16 +715,17 @@
 //  | TEXTURE_DEPTH_CUBE_ARRAY
 Maybe<type::Type*> ParserImpl::depth_texture_type() {
   if (match(Token::Type::kTextureDepth2d))
-    return module_.create<type::DepthTexture>(type::TextureDimension::k2d);
+    return program_.create<type::DepthTexture>(type::TextureDimension::k2d);
 
   if (match(Token::Type::kTextureDepth2dArray))
-    return module_.create<type::DepthTexture>(type::TextureDimension::k2dArray);
+    return program_.create<type::DepthTexture>(
+        type::TextureDimension::k2dArray);
 
   if (match(Token::Type::kTextureDepthCube))
-    return module_.create<type::DepthTexture>(type::TextureDimension::kCube);
+    return program_.create<type::DepthTexture>(type::TextureDimension::kCube);
 
   if (match(Token::Type::kTextureDepthCubeArray))
-    return module_.create<type::DepthTexture>(
+    return program_.create<type::DepthTexture>(
         type::TextureDimension::kCubeArray);
 
   return Failure::kNoMatch;
@@ -909,7 +911,7 @@
   for (auto* deco : access_decos) {
     // If we have an access control decoration then we take it and wrap our
     // type up with that decoration
-    ty = module_.create<type::AccessControl>(
+    ty = program_.create<type::AccessControl>(
         deco->As<ast::AccessDecoration>()->value(), ty);
   }
 
@@ -971,8 +973,8 @@
   if (!type.matched)
     return add_error(peek(), "invalid type alias");
 
-  auto* alias = module_.create<type::Alias>(module_.RegisterSymbol(name.value),
-                                            type.value);
+  auto* alias = program_.create<type::Alias>(
+      program_.RegisterSymbol(name.value), type.value);
   register_constructed(name.value, alias);
 
   return alias;
@@ -1030,16 +1032,16 @@
   }
 
   if (match(Token::Type::kBool))
-    return module_.create<type::Bool>();
+    return program_.create<type::Bool>();
 
   if (match(Token::Type::kF32))
-    return module_.create<type::F32>();
+    return program_.create<type::F32>();
 
   if (match(Token::Type::kI32))
-    return module_.create<type::I32>();
+    return program_.create<type::I32>();
 
   if (match(Token::Type::kU32))
-    return module_.create<type::U32>();
+    return program_.create<type::U32>();
 
   if (t.IsVec2() || t.IsVec3() || t.IsVec4()) {
     next();  // Consume the peek
@@ -1097,7 +1099,7 @@
     if (subtype.errored)
       return Failure::kErrored;
 
-    return module_.create<type::Pointer>(subtype.value, sc.value);
+    return program_.create<type::Pointer>(subtype.value, sc.value);
   });
 }
 
@@ -1114,7 +1116,7 @@
   if (subtype.errored)
     return Failure::kErrored;
 
-  return module_.create<type::Vector>(subtype.value, count);
+  return program_.create<type::Vector>(subtype.value, count);
 }
 
 Expect<type::Type*> ParserImpl::expect_type_decl_array(
@@ -1158,7 +1160,7 @@
   if (subtype.errored)
     return Failure::kErrored;
 
-  return module_.create<type::Matrix>(subtype.value, rows, columns);
+  return program_.create<type::Matrix>(subtype.value, rows, columns);
 }
 
 // storage_class
@@ -1225,7 +1227,7 @@
     return Failure::kErrored;
 
   return create<type::Struct>(
-      module_.RegisterSymbol(name.value),
+      program_.RegisterSymbol(name.value),
       create<ast::Struct>(source, std::move(body.value),
                           std::move(struct_decos.value)));
 }
@@ -1280,7 +1282,7 @@
     return Failure::kErrored;
 
   return create<ast::StructMember>(decl->source,
-                                   module_.RegisterSymbol(decl->name),
+                                   program_.RegisterSymbol(decl->name),
                                    decl->type, std::move(member_decos.value));
 }
 
@@ -1317,7 +1319,7 @@
     return Failure::kErrored;
 
   return create<ast::Function>(
-      header->source, module_.RegisterSymbol(header->name), header->params,
+      header->source, program_.RegisterSymbol(header->name), header->params,
       header->return_type, body.value, func_decos.value);
 }
 
@@ -1326,7 +1328,7 @@
 //   | VOID
 Maybe<type::Type*> ParserImpl::function_type_decl() {
   if (match(Token::Type::kVoid))
-    return module_.create<type::Void>();
+    return program_.create<type::Void>();
 
   return type_decl();
 }
@@ -1386,8 +1388,8 @@
   ast::VariableList ret;
   for (;;) {
     auto* var =
-        create<ast::Variable>(decl->source,                        // source
-                              module_.RegisterSymbol(decl->name),  // symbol
+        create<ast::Variable>(decl->source,                         // source
+                              program_.RegisterSymbol(decl->name),  // symbol
                               ast::StorageClass::kNone,        // storage_class
                               decl->type,                      // type
                               true,                            // is_const
@@ -1657,8 +1659,8 @@
       return add_error(peek(), "missing constructor for const declaration");
 
     auto* var =
-        create<ast::Variable>(decl->source,                        // source
-                              module_.RegisterSymbol(decl->name),  // symbol
+        create<ast::Variable>(decl->source,                         // source
+                              program_.RegisterSymbol(decl->name),  // symbol
                               ast::StorageClass::kNone,        // storage_class
                               decl->type,                      // type
                               true,                            // is_const
@@ -1686,8 +1688,8 @@
   }
 
   auto* var =
-      create<ast::Variable>(decl->source,                        // source
-                            module_.RegisterSymbol(decl->name),  // symbol
+      create<ast::Variable>(decl->source,                         // source
+                            program_.RegisterSymbol(decl->name),  // symbol
                             decl->storage_class,             // storage_class
                             decl->type,                      // type
                             false,                           // is_const
@@ -2089,7 +2091,7 @@
       Source{},
       create<ast::CallExpression>(source,
                                   create<ast::IdentifierExpression>(
-                                      source, module_.RegisterSymbol(name)),
+                                      source, program_.RegisterSymbol(name)),
                                   std::move(params)));
 }
 
@@ -2162,7 +2164,7 @@
 
   if (match(Token::Type::kIdentifier))
     return create<ast::IdentifierExpression>(
-        t.source(), module_.RegisterSymbol(t.to_str()));
+        t.source(), program_.RegisterSymbol(t.to_str()));
 
   auto type = type_decl();
   if (type.errored)
@@ -2238,7 +2240,7 @@
     return postfix_expr(create<ast::MemberAccessorExpression>(
         ident.source, prefix,
         create<ast::IdentifierExpression>(
-            ident.source, module_.RegisterSymbol(ident.value))));
+            ident.source, program_.RegisterSymbol(ident.value))));
   }
 
   return prefix;
@@ -2738,19 +2740,19 @@
 Maybe<ast::Literal*> ParserImpl::const_literal() {
   auto t = peek();
   if (match(Token::Type::kTrue)) {
-    auto* type = module_.create<type::Bool>();
+    auto* type = program_.create<type::Bool>();
     return create<ast::BoolLiteral>(Source{}, type, true);
   }
   if (match(Token::Type::kFalse)) {
-    auto* type = module_.create<type::Bool>();
+    auto* type = program_.create<type::Bool>();
     return create<ast::BoolLiteral>(Source{}, type, false);
   }
   if (match(Token::Type::kSintLiteral)) {
-    auto* type = module_.create<type::I32>();
+    auto* type = program_.create<type::I32>();
     return create<ast::SintLiteral>(Source{}, type, t.to_i32());
   }
   if (match(Token::Type::kUintLiteral)) {
-    auto* type = module_.create<type::U32>();
+    auto* type = program_.create<type::U32>();
     return create<ast::UintLiteral>(Source{}, type, t.to_u32());
   }
   if (match(Token::Type::kFloatLiteral)) {
@@ -2759,7 +2761,7 @@
       next();  // Consume 'f'
       add_error(p.source(), "float literals must not be suffixed with 'f'");
     }
-    auto* type = module_.create<type::F32>();
+    auto* type = program_.create<type::F32>();
     return create<ast::FloatLiteral>(Source{}, type, t.to_f32());
   }
   return Failure::kNoMatch;
diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h
index 838f0bb..cada777 100644
--- a/src/reader/wgsl/parser_impl.h
+++ b/src/reader/wgsl/parser_impl.h
@@ -38,7 +38,6 @@
 #include "src/ast/if_statement.h"
 #include "src/ast/literal.h"
 #include "src/ast/loop_statement.h"
-#include "src/ast/module.h"
 #include "src/ast/pipeline_stage.h"
 #include "src/ast/return_statement.h"
 #include "src/ast/statement.h"
@@ -53,6 +52,7 @@
 #include "src/ast/variable_decoration.h"
 #include "src/diagnostic/diagnostic.h"
 #include "src/diagnostic/formatter.h"
+#include "src/program.h"
 #include "src/reader/wgsl/parser_impl_detail.h"
 #include "src/reader/wgsl/token.h"
 #include "src/type/storage_texture_type.h"
@@ -307,11 +307,11 @@
   /// @returns the diagnostic messages
   diag::List& diagnostics() { return diags_; }
 
-  /// @returns the module. The module in the parser will be reset after this.
-  ast::Module module() { return std::move(module_); }
+  /// @returns the program. The program in the parser will be reset after this.
+  Program program() { return std::move(program_); }
 
   /// @returns a pointer to the module, without resetting it.
-  ast::Module& get_module() { return module_; }
+  Program& get_program() { return program_; }
 
   /// @returns the next token
   Token next();
@@ -829,7 +829,7 @@
   /// @returns the node pointer
   template <typename T, typename... ARGS>
   T* create(ARGS&&... args) {
-    return module_.create<T>(std::forward<ARGS>(args)...);
+    return program_.create<T>(std::forward<ARGS>(args)...);
   }
 
   diag::List diags_;
@@ -839,7 +839,7 @@
   std::vector<Token::Type> sync_tokens_;
   int silence_errors_ = 0;
   std::unordered_map<std::string, type::Type*> registered_constructs_;
-  ast::Module module_;
+  Program program_;
   size_t max_errors_ = 25;
 };
 
diff --git a/src/reader/wgsl/parser_impl_additive_expression_test.cc b/src/reader/wgsl/parser_impl_additive_expression_test.cc
index 69b5623..f7fc99b 100644
--- a/src/reader/wgsl/parser_impl_additive_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_additive_expression_test.cc
@@ -39,7 +39,7 @@
 
   ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
   auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
@@ -62,7 +62,7 @@
 
   ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
   auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
diff --git a/src/reader/wgsl/parser_impl_and_expression_test.cc b/src/reader/wgsl/parser_impl_and_expression_test.cc
index e50c345..68979f9 100644
--- a/src/reader/wgsl/parser_impl_and_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_and_expression_test.cc
@@ -39,7 +39,7 @@
 
   ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
   auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
diff --git a/src/reader/wgsl/parser_impl_assignment_stmt_test.cc b/src/reader/wgsl/parser_impl_assignment_stmt_test.cc
index a770895..5234057 100644
--- a/src/reader/wgsl/parser_impl_assignment_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_assignment_stmt_test.cc
@@ -42,7 +42,7 @@
 
   ASSERT_TRUE(e->lhs()->Is<ast::IdentifierExpression>());
   auto* ident = e->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(e->rhs()->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(e->rhs()->Is<ast::ScalarConstructorExpression>());
@@ -77,7 +77,7 @@
 
   ASSERT_TRUE(mem->member()->Is<ast::IdentifierExpression>());
   auto* ident = mem->member()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("d"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("d"));
 
   ASSERT_TRUE(mem->structure()->Is<ast::ArrayAccessorExpression>());
   auto* ary = mem->structure()->As<ast::ArrayAccessorExpression>();
@@ -93,18 +93,18 @@
   mem = ary->array()->As<ast::MemberAccessorExpression>();
   ASSERT_TRUE(mem->member()->Is<ast::IdentifierExpression>());
   ident = mem->member()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("c"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("c"));
 
   ASSERT_TRUE(mem->structure()->Is<ast::MemberAccessorExpression>());
   mem = mem->structure()->As<ast::MemberAccessorExpression>();
 
   ASSERT_TRUE(mem->structure()->Is<ast::IdentifierExpression>());
   ident = mem->structure()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(mem->member()->Is<ast::IdentifierExpression>());
   ident = mem->member()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("b"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("b"));
 }
 
 TEST_F(ParserImplTest, AssignmentStmt_MissingEqual) {
diff --git a/src/reader/wgsl/parser_impl_call_stmt_test.cc b/src/reader/wgsl/parser_impl_call_stmt_test.cc
index 1fd8f77..a8f3850 100644
--- a/src/reader/wgsl/parser_impl_call_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_call_stmt_test.cc
@@ -38,7 +38,7 @@
 
   ASSERT_TRUE(c->func()->Is<ast::IdentifierExpression>());
   auto* ident = c->func()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   EXPECT_EQ(c->params().size(), 0u);
 }
@@ -56,7 +56,7 @@
 
   ASSERT_TRUE(c->func()->Is<ast::IdentifierExpression>());
   auto* ident = c->func()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   EXPECT_EQ(c->params().size(), 3u);
   EXPECT_TRUE(c->params()[0]->Is<ast::ConstructorExpression>());
diff --git a/src/reader/wgsl/parser_impl_equality_expression_test.cc b/src/reader/wgsl/parser_impl_equality_expression_test.cc
index fffec25..89600cb 100644
--- a/src/reader/wgsl/parser_impl_equality_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_equality_expression_test.cc
@@ -39,7 +39,7 @@
 
   ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
   auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
@@ -62,7 +62,7 @@
 
   ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
   auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
diff --git a/src/reader/wgsl/parser_impl_exclusive_or_expression_test.cc b/src/reader/wgsl/parser_impl_exclusive_or_expression_test.cc
index d50a6fa..cf821bf 100644
--- a/src/reader/wgsl/parser_impl_exclusive_or_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_exclusive_or_expression_test.cc
@@ -39,7 +39,7 @@
 
   ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
   auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
diff --git a/src/reader/wgsl/parser_impl_function_decl_test.cc b/src/reader/wgsl/parser_impl_function_decl_test.cc
index 17b9fd1..4a58b0c 100644
--- a/src/reader/wgsl/parser_impl_function_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_function_decl_test.cc
@@ -37,13 +37,13 @@
   EXPECT_TRUE(f.matched);
   ASSERT_NE(f.value, nullptr);
 
-  EXPECT_EQ(f->symbol(), p->get_module().RegisterSymbol("main"));
+  EXPECT_EQ(f->symbol(), p->get_program().RegisterSymbol("main"));
   ASSERT_NE(f->return_type(), nullptr);
   EXPECT_TRUE(f->return_type()->Is<type::Void>());
 
   ASSERT_EQ(f->params().size(), 2u);
-  EXPECT_EQ(f->params()[0]->symbol(), p->get_module().RegisterSymbol("a"));
-  EXPECT_EQ(f->params()[1]->symbol(), p->get_module().RegisterSymbol("b"));
+  EXPECT_EQ(f->params()[0]->symbol(), p->get_program().RegisterSymbol("a"));
+  EXPECT_EQ(f->params()[1]->symbol(), p->get_program().RegisterSymbol("b"));
 
   ASSERT_NE(f->return_type(), nullptr);
   EXPECT_TRUE(f->return_type()->Is<type::Void>());
@@ -65,7 +65,7 @@
   EXPECT_TRUE(f.matched);
   ASSERT_NE(f.value, nullptr);
 
-  EXPECT_EQ(f->symbol(), p->get_module().RegisterSymbol("main"));
+  EXPECT_EQ(f->symbol(), p->get_program().RegisterSymbol("main"));
   ASSERT_NE(f->return_type(), nullptr);
   EXPECT_TRUE(f->return_type()->Is<type::Void>());
   ASSERT_EQ(f->params().size(), 0u);
@@ -103,7 +103,7 @@
   EXPECT_TRUE(f.matched);
   ASSERT_NE(f.value, nullptr);
 
-  EXPECT_EQ(f->symbol(), p->get_module().RegisterSymbol("main"));
+  EXPECT_EQ(f->symbol(), p->get_program().RegisterSymbol("main"));
   ASSERT_NE(f->return_type(), nullptr);
   EXPECT_TRUE(f->return_type()->Is<type::Void>());
   ASSERT_EQ(f->params().size(), 0u);
@@ -148,7 +148,7 @@
   EXPECT_TRUE(f.matched);
   ASSERT_NE(f.value, nullptr);
 
-  EXPECT_EQ(f->symbol(), p->get_module().RegisterSymbol("main"));
+  EXPECT_EQ(f->symbol(), p->get_program().RegisterSymbol("main"));
   ASSERT_NE(f->return_type(), nullptr);
   EXPECT_TRUE(f->return_type()->Is<type::Void>());
   ASSERT_EQ(f->params().size(), 0u);
diff --git a/src/reader/wgsl/parser_impl_function_header_test.cc b/src/reader/wgsl/parser_impl_function_header_test.cc
index 1a77313..0b7fd8e 100644
--- a/src/reader/wgsl/parser_impl_function_header_test.cc
+++ b/src/reader/wgsl/parser_impl_function_header_test.cc
@@ -33,8 +33,8 @@
 
   EXPECT_EQ(f->name, "main");
   ASSERT_EQ(f->params.size(), 2u);
-  EXPECT_EQ(f->params[0]->symbol(), p->get_module().RegisterSymbol("a"));
-  EXPECT_EQ(f->params[1]->symbol(), p->get_module().RegisterSymbol("b"));
+  EXPECT_EQ(f->params[0]->symbol(), p->get_program().RegisterSymbol("a"));
+  EXPECT_EQ(f->params[1]->symbol(), p->get_program().RegisterSymbol("b"));
   EXPECT_TRUE(f->return_type->Is<type::Void>());
 }
 
diff --git a/src/reader/wgsl/parser_impl_function_type_decl_test.cc b/src/reader/wgsl/parser_impl_function_type_decl_test.cc
index f3f16bf..57cc4b0 100644
--- a/src/reader/wgsl/parser_impl_function_type_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_function_type_decl_test.cc
@@ -29,7 +29,7 @@
 TEST_F(ParserImplTest, FunctionTypeDecl_Void) {
   auto p = parser("void");
 
-  auto& mod = p->get_module();
+  auto& mod = p->get_program();
   auto* v = mod.create<type::Void>();
 
   auto e = p->function_type_decl();
@@ -42,7 +42,7 @@
 TEST_F(ParserImplTest, FunctionTypeDecl_Type) {
   auto p = parser("vec2<f32>");
 
-  auto& mod = p->get_module();
+  auto& mod = p->get_program();
   auto* f32 = mod.create<type::F32>();
   auto* vec2 = mod.create<type::Vector>(f32, 2);
 
diff --git a/src/reader/wgsl/parser_impl_global_constant_decl_test.cc b/src/reader/wgsl/parser_impl_global_constant_decl_test.cc
index 149b6d9..9bb96e3 100644
--- a/src/reader/wgsl/parser_impl_global_constant_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_global_constant_decl_test.cc
@@ -33,7 +33,7 @@
   ASSERT_NE(e.value, nullptr);
 
   EXPECT_TRUE(e->is_const());
-  EXPECT_EQ(e->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(e->symbol(), p->get_program().RegisterSymbol("a"));
   ASSERT_NE(e->type(), nullptr);
   EXPECT_TRUE(e->type()->Is<type::F32>());
 
diff --git a/src/reader/wgsl/parser_impl_global_decl_test.cc b/src/reader/wgsl/parser_impl_global_decl_test.cc
index 3875ca0..b1f7be6 100644
--- a/src/reader/wgsl/parser_impl_global_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_global_decl_test.cc
@@ -34,11 +34,11 @@
   p->expect_global_decl();
   ASSERT_FALSE(p->has_error()) << p->error();
 
-  auto& m = p->get_module();
+  auto& m = p->get_program();
   ASSERT_EQ(m.global_variables().size(), 1u);
 
   auto* v = m.global_variables()[0];
-  EXPECT_EQ(v->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(v->symbol(), p->get_program().RegisterSymbol("a"));
 }
 
 TEST_F(ParserImplTest, GlobalDecl_GlobalVariable_Invalid) {
@@ -60,11 +60,11 @@
   p->expect_global_decl();
   ASSERT_FALSE(p->has_error()) << p->error();
 
-  auto& m = p->get_module();
+  auto& m = p->get_program();
   ASSERT_EQ(m.global_variables().size(), 1u);
 
   auto* v = m.global_variables()[0];
-  EXPECT_EQ(v->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(v->symbol(), p->get_program().RegisterSymbol("a"));
 }
 
 TEST_F(ParserImplTest, GlobalDecl_GlobalConstant_Invalid) {
@@ -86,7 +86,7 @@
   p->expect_global_decl();
   ASSERT_FALSE(p->has_error()) << p->error();
 
-  auto& m = p->get_module();
+  auto& m = p->get_program();
   ASSERT_EQ(m.constructed_types().size(), 1u);
   ASSERT_TRUE(m.constructed_types()[0]->Is<type::Alias>());
   EXPECT_EQ(
@@ -103,15 +103,15 @@
   p->expect_global_decl();
   ASSERT_FALSE(p->has_error()) << p->error();
 
-  auto& m = p->get_module();
+  auto& m = p->get_program();
   ASSERT_EQ(m.constructed_types().size(), 2u);
   ASSERT_TRUE(m.constructed_types()[0]->Is<type::Struct>());
   auto* str = m.constructed_types()[0]->As<type::Struct>();
-  EXPECT_EQ(str->symbol(), p->get_module().RegisterSymbol("A"));
+  EXPECT_EQ(str->symbol(), p->get_program().RegisterSymbol("A"));
 
   ASSERT_TRUE(m.constructed_types()[1]->Is<type::Alias>());
   auto* alias = m.constructed_types()[1]->As<type::Alias>();
-  EXPECT_EQ(alias->symbol(), p->get_module().RegisterSymbol("B"));
+  EXPECT_EQ(alias->symbol(), p->get_program().RegisterSymbol("B"));
   EXPECT_EQ(alias->type(), str);
 }
 
@@ -134,7 +134,7 @@
   p->expect_global_decl();
   ASSERT_FALSE(p->has_error()) << p->error();
 
-  auto& m = p->get_module();
+  auto& m = p->get_program();
   ASSERT_EQ(m.Functions().size(), 1u);
   EXPECT_EQ(m.SymbolToName(m.Functions()[0]->symbol()), "main");
 }
@@ -144,7 +144,7 @@
   p->expect_global_decl();
   ASSERT_FALSE(p->has_error()) << p->error();
 
-  auto& m = p->get_module();
+  auto& m = p->get_program();
   ASSERT_EQ(m.Functions().size(), 1u);
   EXPECT_EQ(m.SymbolToName(m.Functions()[0]->symbol()), "main");
 }
@@ -161,7 +161,7 @@
   p->expect_global_decl();
   ASSERT_FALSE(p->has_error()) << p->error();
 
-  auto& m = p->get_module();
+  auto& m = p->get_program();
   ASSERT_EQ(m.constructed_types().size(), 1u);
 
   auto* t = m.constructed_types()[0];
@@ -169,7 +169,7 @@
   ASSERT_TRUE(t->Is<type::Struct>());
 
   auto* str = t->As<type::Struct>();
-  EXPECT_EQ(str->symbol(), p->get_module().RegisterSymbol("A"));
+  EXPECT_EQ(str->symbol(), p->get_program().RegisterSymbol("A"));
   EXPECT_EQ(str->impl()->members().size(), 2u);
 }
 
@@ -180,7 +180,7 @@
   p->expect_global_decl();
   ASSERT_FALSE(p->has_error()) << p->error();
 
-  auto& m = p->get_module();
+  auto& m = p->get_program();
   ASSERT_EQ(m.constructed_types().size(), 1u);
 
   auto* t = m.constructed_types()[0];
@@ -188,7 +188,7 @@
   ASSERT_TRUE(t->Is<type::Struct>());
 
   auto* str = t->As<type::Struct>();
-  EXPECT_EQ(str->symbol(), p->get_module().RegisterSymbol("A"));
+  EXPECT_EQ(str->symbol(), p->get_program().RegisterSymbol("A"));
   EXPECT_EQ(str->impl()->members().size(), 1u);
   EXPECT_FALSE(str->IsBlockDecorated());
 
@@ -204,7 +204,7 @@
   p->expect_global_decl();
   ASSERT_FALSE(p->has_error()) << p->error();
 
-  auto& m = p->get_module();
+  auto& m = p->get_program();
   ASSERT_EQ(m.constructed_types().size(), 1u);
 
   auto* t = m.constructed_types()[0];
@@ -212,7 +212,7 @@
   ASSERT_TRUE(t->Is<type::Struct>());
 
   auto* str = t->As<type::Struct>();
-  EXPECT_EQ(str->symbol(), p->get_module().RegisterSymbol("A"));
+  EXPECT_EQ(str->symbol(), p->get_program().RegisterSymbol("A"));
   EXPECT_EQ(str->impl()->members().size(), 1u);
   EXPECT_TRUE(str->IsBlockDecorated());
 }
diff --git a/src/reader/wgsl/parser_impl_global_variable_decl_test.cc b/src/reader/wgsl/parser_impl_global_variable_decl_test.cc
index 84c392d..28146d8 100644
--- a/src/reader/wgsl/parser_impl_global_variable_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_global_variable_decl_test.cc
@@ -36,7 +36,7 @@
   EXPECT_FALSE(e.errored);
   ASSERT_NE(e.value, nullptr);
 
-  EXPECT_EQ(e->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(e->symbol(), p->get_program().RegisterSymbol("a"));
   EXPECT_TRUE(e->type()->Is<type::F32>());
   EXPECT_EQ(e->storage_class(), ast::StorageClass::kOutput);
 
@@ -59,7 +59,7 @@
   EXPECT_FALSE(e.errored);
   ASSERT_NE(e.value, nullptr);
 
-  EXPECT_EQ(e->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(e->symbol(), p->get_program().RegisterSymbol("a"));
   EXPECT_TRUE(e->type()->Is<type::F32>());
   EXPECT_EQ(e->storage_class(), ast::StorageClass::kOutput);
 
@@ -84,7 +84,7 @@
   EXPECT_FALSE(e.errored);
   ASSERT_NE(e.value, nullptr);
 
-  EXPECT_EQ(e->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(e->symbol(), p->get_program().RegisterSymbol("a"));
   ASSERT_NE(e->type(), nullptr);
   EXPECT_TRUE(e->type()->Is<type::F32>());
   EXPECT_EQ(e->storage_class(), ast::StorageClass::kOutput);
@@ -114,7 +114,7 @@
   EXPECT_FALSE(e.errored);
   ASSERT_NE(e.value, nullptr);
 
-  EXPECT_EQ(e->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(e->symbol(), p->get_program().RegisterSymbol("a"));
   ASSERT_NE(e->type(), nullptr);
   EXPECT_TRUE(e->type()->Is<type::F32>());
   EXPECT_EQ(e->storage_class(), ast::StorageClass::kOutput);
diff --git a/src/reader/wgsl/parser_impl_inclusive_or_expression_test.cc b/src/reader/wgsl/parser_impl_inclusive_or_expression_test.cc
index 6612866..b900de9 100644
--- a/src/reader/wgsl/parser_impl_inclusive_or_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_inclusive_or_expression_test.cc
@@ -39,7 +39,7 @@
 
   ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
   auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
diff --git a/src/reader/wgsl/parser_impl_logical_and_expression_test.cc b/src/reader/wgsl/parser_impl_logical_and_expression_test.cc
index 7218c70..0a392b9 100644
--- a/src/reader/wgsl/parser_impl_logical_and_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_logical_and_expression_test.cc
@@ -39,7 +39,7 @@
 
   ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
   auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
diff --git a/src/reader/wgsl/parser_impl_logical_or_expression_test.cc b/src/reader/wgsl/parser_impl_logical_or_expression_test.cc
index 67f5674..921d9ca 100644
--- a/src/reader/wgsl/parser_impl_logical_or_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_logical_or_expression_test.cc
@@ -39,7 +39,7 @@
 
   ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
   auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
diff --git a/src/reader/wgsl/parser_impl_multiplicative_expression_test.cc b/src/reader/wgsl/parser_impl_multiplicative_expression_test.cc
index 8cc5101..c0b547c 100644
--- a/src/reader/wgsl/parser_impl_multiplicative_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_multiplicative_expression_test.cc
@@ -39,7 +39,7 @@
 
   ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
   auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
@@ -62,7 +62,7 @@
 
   ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
   auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
@@ -85,7 +85,7 @@
 
   ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
   auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
diff --git a/src/reader/wgsl/parser_impl_param_list_test.cc b/src/reader/wgsl/parser_impl_param_list_test.cc
index a8a9106..fb87002 100644
--- a/src/reader/wgsl/parser_impl_param_list_test.cc
+++ b/src/reader/wgsl/parser_impl_param_list_test.cc
@@ -30,7 +30,7 @@
 TEST_F(ParserImplTest, ParamList_Single) {
   auto p = parser("a : i32");
 
-  auto& mod = p->get_module();
+  auto& mod = p->get_program();
   auto* i32 = mod.create<type::I32>();
 
   auto e = p->expect_param_list();
@@ -38,7 +38,7 @@
   ASSERT_FALSE(e.errored);
   EXPECT_EQ(e.value.size(), 1u);
 
-  EXPECT_EQ(e.value[0]->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(e.value[0]->symbol(), p->get_program().RegisterSymbol("a"));
   EXPECT_EQ(e.value[0]->type(), i32);
   EXPECT_TRUE(e.value[0]->is_const());
 
@@ -51,7 +51,7 @@
 TEST_F(ParserImplTest, ParamList_Multiple) {
   auto p = parser("a : i32, b: f32, c: vec2<f32>");
 
-  auto& mod = p->get_module();
+  auto& mod = p->get_program();
   auto* i32 = mod.create<type::I32>();
   auto* f32 = mod.create<type::F32>();
   auto* vec2 = mod.create<type::Vector>(f32, 2);
@@ -61,7 +61,7 @@
   ASSERT_FALSE(e.errored);
   EXPECT_EQ(e.value.size(), 3u);
 
-  EXPECT_EQ(e.value[0]->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(e.value[0]->symbol(), p->get_program().RegisterSymbol("a"));
   EXPECT_EQ(e.value[0]->type(), i32);
   EXPECT_TRUE(e.value[0]->is_const());
 
@@ -70,7 +70,7 @@
   ASSERT_EQ(e.value[0]->source().range.end.line, 1u);
   ASSERT_EQ(e.value[0]->source().range.end.column, 2u);
 
-  EXPECT_EQ(e.value[1]->symbol(), p->get_module().RegisterSymbol("b"));
+  EXPECT_EQ(e.value[1]->symbol(), p->get_program().RegisterSymbol("b"));
   EXPECT_EQ(e.value[1]->type(), f32);
   EXPECT_TRUE(e.value[1]->is_const());
 
@@ -79,7 +79,7 @@
   ASSERT_EQ(e.value[1]->source().range.end.line, 1u);
   ASSERT_EQ(e.value[1]->source().range.end.column, 11u);
 
-  EXPECT_EQ(e.value[2]->symbol(), p->get_module().RegisterSymbol("c"));
+  EXPECT_EQ(e.value[2]->symbol(), p->get_program().RegisterSymbol("c"));
   EXPECT_EQ(e.value[2]->type(), vec2);
   EXPECT_TRUE(e.value[2]->is_const());
 
diff --git a/src/reader/wgsl/parser_impl_postfix_expression_test.cc b/src/reader/wgsl/parser_impl_postfix_expression_test.cc
index afe83ea..e03eed2 100644
--- a/src/reader/wgsl/parser_impl_postfix_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_postfix_expression_test.cc
@@ -42,7 +42,7 @@
 
   ASSERT_TRUE(ary->array()->Is<ast::IdentifierExpression>());
   auto* ident = ary->array()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(ary->idx_expr()->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(ary->idx_expr()->Is<ast::ScalarConstructorExpression>());
@@ -64,7 +64,7 @@
 
   ASSERT_TRUE(ary->array()->Is<ast::IdentifierExpression>());
   auto* ident = ary->array()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(ary->idx_expr()->Is<ast::BinaryExpression>());
 }
@@ -112,7 +112,7 @@
 
   ASSERT_TRUE(c->func()->Is<ast::IdentifierExpression>());
   auto* func = c->func()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(func->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(func->symbol(), p->get_program().RegisterSymbol("a"));
 
   EXPECT_EQ(c->params().size(), 0u);
 }
@@ -130,7 +130,7 @@
 
   ASSERT_TRUE(c->func()->Is<ast::IdentifierExpression>());
   auto* func = c->func()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(func->symbol(), p->get_module().RegisterSymbol("test"));
+  EXPECT_EQ(func->symbol(), p->get_program().RegisterSymbol("test"));
 
   EXPECT_EQ(c->params().size(), 3u);
   EXPECT_TRUE(c->params()[0]->Is<ast::ConstructorExpression>());
@@ -180,11 +180,11 @@
   auto* m = e->As<ast::MemberAccessorExpression>();
   ASSERT_TRUE(m->structure()->Is<ast::IdentifierExpression>());
   EXPECT_EQ(m->structure()->As<ast::IdentifierExpression>()->symbol(),
-            p->get_module().RegisterSymbol("a"));
+            p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(m->member()->Is<ast::IdentifierExpression>());
   EXPECT_EQ(m->member()->As<ast::IdentifierExpression>()->symbol(),
-            p->get_module().RegisterSymbol("b"));
+            p->get_program().RegisterSymbol("b"));
 }
 
 TEST_F(ParserImplTest, PostfixExpression_MemberAccesssor_InvalidIdent) {
diff --git a/src/reader/wgsl/parser_impl_primary_expression_test.cc b/src/reader/wgsl/parser_impl_primary_expression_test.cc
index 74ddfc3..072ade2 100644
--- a/src/reader/wgsl/parser_impl_primary_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_primary_expression_test.cc
@@ -41,7 +41,7 @@
   ASSERT_NE(e.value, nullptr);
   ASSERT_TRUE(e->Is<ast::IdentifierExpression>());
   auto* ident = e->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 }
 
 TEST_F(ParserImplTest, PrimaryExpression_TypeDecl) {
@@ -193,7 +193,7 @@
 TEST_F(ParserImplTest, PrimaryExpression_Cast) {
   auto p = parser("f32(1)");
 
-  auto& mod = p->get_module();
+  auto& mod = p->get_program();
   auto* f32 = mod.create<type::F32>();
 
   auto e = p->primary_expression();
@@ -215,7 +215,7 @@
 TEST_F(ParserImplTest, PrimaryExpression_Bitcast) {
   auto p = parser("bitcast<f32>(1)");
 
-  auto& mod = p->get_module();
+  auto& mod = p->get_program();
   auto* f32 = mod.create<type::F32>();
 
   auto e = p->primary_expression();
diff --git a/src/reader/wgsl/parser_impl_relational_expression_test.cc b/src/reader/wgsl/parser_impl_relational_expression_test.cc
index b17292e..57315db 100644
--- a/src/reader/wgsl/parser_impl_relational_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_relational_expression_test.cc
@@ -39,7 +39,7 @@
 
   ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
   auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
@@ -62,7 +62,7 @@
 
   ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
   auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
@@ -85,7 +85,7 @@
 
   ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
   auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
@@ -108,7 +108,7 @@
 
   ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
   auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
diff --git a/src/reader/wgsl/parser_impl_shift_expression_test.cc b/src/reader/wgsl/parser_impl_shift_expression_test.cc
index 41cee53..5bdb2f0 100644
--- a/src/reader/wgsl/parser_impl_shift_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_shift_expression_test.cc
@@ -39,7 +39,7 @@
 
   ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
   auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
@@ -62,7 +62,7 @@
 
   ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
   auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
diff --git a/src/reader/wgsl/parser_impl_struct_body_decl_test.cc b/src/reader/wgsl/parser_impl_struct_body_decl_test.cc
index bbfdce1..5c4e0cf 100644
--- a/src/reader/wgsl/parser_impl_struct_body_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_struct_body_decl_test.cc
@@ -25,7 +25,7 @@
 TEST_F(ParserImplTest, StructBodyDecl_Parses) {
   auto p = parser("{a : i32;}");
 
-  auto& mod = p->get_module();
+  auto& mod = p->get_program();
   auto* i32 = mod.create<type::I32>();
 
   auto m = p->expect_struct_body_decl();
@@ -34,7 +34,7 @@
   ASSERT_EQ(m.value.size(), 1u);
 
   const auto* mem = m.value[0];
-  EXPECT_EQ(mem->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(mem->symbol(), p->get_program().RegisterSymbol("a"));
   EXPECT_EQ(mem->type(), i32);
   EXPECT_EQ(mem->decorations().size(), 0u);
 }
diff --git a/src/reader/wgsl/parser_impl_struct_decl_test.cc b/src/reader/wgsl/parser_impl_struct_decl_test.cc
index 9680c4d..ccaaddb 100644
--- a/src/reader/wgsl/parser_impl_struct_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_struct_decl_test.cc
@@ -14,9 +14,9 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/struct_block_decoration.h"
-#include "src/type/struct_type.h"
 #include "src/reader/wgsl/parser_impl.h"
 #include "src/reader/wgsl/parser_impl_test_helper.h"
+#include "src/type/struct_type.h"
 
 namespace tint {
 namespace reader {
@@ -39,12 +39,12 @@
   EXPECT_FALSE(s.errored);
   EXPECT_TRUE(s.matched);
   ASSERT_NE(s.value, nullptr);
-  ASSERT_EQ(s->symbol(), p->get_module().RegisterSymbol("S"));
+  ASSERT_EQ(s->symbol(), p->get_program().RegisterSymbol("S"));
   ASSERT_EQ(s->impl()->members().size(), 2u);
   EXPECT_EQ(s->impl()->members()[0]->symbol(),
-            p->get_module().RegisterSymbol("a"));
+            p->get_program().RegisterSymbol("a"));
   EXPECT_EQ(s->impl()->members()[1]->symbol(),
-            p->get_module().RegisterSymbol("b"));
+            p->get_program().RegisterSymbol("b"));
 }
 
 TEST_F(ParserImplTest, StructDecl_ParsesWithDecoration) {
@@ -63,12 +63,12 @@
   EXPECT_FALSE(s.errored);
   EXPECT_TRUE(s.matched);
   ASSERT_NE(s.value, nullptr);
-  ASSERT_EQ(s->symbol(), p->get_module().RegisterSymbol("B"));
+  ASSERT_EQ(s->symbol(), p->get_program().RegisterSymbol("B"));
   ASSERT_EQ(s->impl()->members().size(), 2u);
   EXPECT_EQ(s->impl()->members()[0]->symbol(),
-            p->get_module().RegisterSymbol("a"));
+            p->get_program().RegisterSymbol("a"));
   EXPECT_EQ(s->impl()->members()[1]->symbol(),
-            p->get_module().RegisterSymbol("b"));
+            p->get_program().RegisterSymbol("b"));
   ASSERT_EQ(s->impl()->decorations().size(), 1u);
   EXPECT_TRUE(s->impl()->decorations()[0]->Is<ast::StructBlockDecoration>());
 }
@@ -90,12 +90,12 @@
   EXPECT_FALSE(s.errored);
   EXPECT_TRUE(s.matched);
   ASSERT_NE(s.value, nullptr);
-  ASSERT_EQ(s->symbol(), p->get_module().RegisterSymbol("S"));
+  ASSERT_EQ(s->symbol(), p->get_program().RegisterSymbol("S"));
   ASSERT_EQ(s->impl()->members().size(), 2u);
   EXPECT_EQ(s->impl()->members()[0]->symbol(),
-            p->get_module().RegisterSymbol("a"));
+            p->get_program().RegisterSymbol("a"));
   EXPECT_EQ(s->impl()->members()[1]->symbol(),
-            p->get_module().RegisterSymbol("b"));
+            p->get_program().RegisterSymbol("b"));
   ASSERT_EQ(s->impl()->decorations().size(), 2u);
   EXPECT_TRUE(s->impl()->decorations()[0]->Is<ast::StructBlockDecoration>());
   EXPECT_TRUE(s->impl()->decorations()[1]->Is<ast::StructBlockDecoration>());
diff --git a/src/reader/wgsl/parser_impl_struct_member_test.cc b/src/reader/wgsl/parser_impl_struct_member_test.cc
index 554e1d7..0460b80 100644
--- a/src/reader/wgsl/parser_impl_struct_member_test.cc
+++ b/src/reader/wgsl/parser_impl_struct_member_test.cc
@@ -26,7 +26,7 @@
 TEST_F(ParserImplTest, StructMember_Parses) {
   auto p = parser("a : i32;");
 
-  auto& mod = p->get_module();
+  auto& mod = p->get_program();
   auto* i32 = mod.create<type::I32>();
 
   auto decos = p->decoration_list();
@@ -39,7 +39,7 @@
   ASSERT_FALSE(m.errored);
   ASSERT_NE(m.value, nullptr);
 
-  EXPECT_EQ(m->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(m->symbol(), p->get_program().RegisterSymbol("a"));
   EXPECT_EQ(m->type(), i32);
   EXPECT_EQ(m->decorations().size(), 0u);
 
@@ -52,7 +52,7 @@
 TEST_F(ParserImplTest, StructMember_ParsesWithDecoration) {
   auto p = parser("[[offset(2)]] a : i32;");
 
-  auto& mod = p->get_module();
+  auto& mod = p->get_program();
   auto* i32 = mod.create<type::I32>();
 
   auto decos = p->decoration_list();
@@ -65,7 +65,7 @@
   ASSERT_FALSE(m.errored);
   ASSERT_NE(m.value, nullptr);
 
-  EXPECT_EQ(m->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(m->symbol(), p->get_program().RegisterSymbol("a"));
   EXPECT_EQ(m->type(), i32);
   EXPECT_EQ(m->decorations().size(), 1u);
   EXPECT_TRUE(m->decorations()[0]->Is<ast::StructMemberOffsetDecoration>());
@@ -83,7 +83,7 @@
   auto p = parser(R"([[offset(2)]]
 [[offset(4)]] a : i32;)");
 
-  auto& mod = p->get_module();
+  auto& mod = p->get_program();
   auto* i32 = mod.create<type::I32>();
 
   auto decos = p->decoration_list();
@@ -96,7 +96,7 @@
   ASSERT_FALSE(m.errored);
   ASSERT_NE(m.value, nullptr);
 
-  EXPECT_EQ(m->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(m->symbol(), p->get_program().RegisterSymbol("a"));
   EXPECT_EQ(m->type(), i32);
   EXPECT_EQ(m->decorations().size(), 2u);
   EXPECT_TRUE(m->decorations()[0]->Is<ast::StructMemberOffsetDecoration>());
diff --git a/src/reader/wgsl/parser_impl_test.cc b/src/reader/wgsl/parser_impl_test.cc
index 3065a08..6da4d6d 100644
--- a/src/reader/wgsl/parser_impl_test.cc
+++ b/src/reader/wgsl/parser_impl_test.cc
@@ -39,7 +39,7 @@
 )");
   ASSERT_TRUE(p->Parse()) << p->error();
 
-  auto& m = p->get_module();
+  auto& m = p->get_program();
   ASSERT_EQ(1u, m.Functions().size());
   ASSERT_EQ(1u, m.global_variables().size());
 }
diff --git a/src/reader/wgsl/parser_impl_test_helper.h b/src/reader/wgsl/parser_impl_test_helper.h
index 184eddd..7a7efa7 100644
--- a/src/reader/wgsl/parser_impl_test_helper.h
+++ b/src/reader/wgsl/parser_impl_test_helper.h
@@ -29,7 +29,7 @@
 namespace wgsl {
 
 /// WGSL Parser test class
-class ParserImplTest : public testing::Test, public ast::BuilderWithModule {
+class ParserImplTest : public testing::Test, public ast::BuilderWithProgram {
  public:
   /// Constructor
   ParserImplTest();
@@ -52,7 +52,7 @@
 /// WGSL Parser test class with param
 template <typename T>
 class ParserImplTestWithParam : public testing::TestWithParam<T>,
-                                public ast::BuilderWithModule {
+                                public ast::BuilderWithProgram {
  public:
   /// Constructor
   ParserImplTestWithParam() = default;
diff --git a/src/reader/wgsl/parser_impl_type_alias_test.cc b/src/reader/wgsl/parser_impl_type_alias_test.cc
index da890b5..414714b 100644
--- a/src/reader/wgsl/parser_impl_type_alias_test.cc
+++ b/src/reader/wgsl/parser_impl_type_alias_test.cc
@@ -28,7 +28,7 @@
 TEST_F(ParserImplTest, TypeDecl_ParsesType) {
   auto p = parser("type a = i32");
 
-  auto& mod = p->get_module();
+  auto& mod = p->get_program();
   auto* i32 = mod.create<type::I32>();
 
   auto t = p->type_alias();
@@ -45,7 +45,7 @@
 TEST_F(ParserImplTest, TypeDecl_ParsesStruct_Ident) {
   auto p = parser("type a = B");
 
-  type::Struct str(p->get_module().RegisterSymbol("B"), {});
+  type::Struct str(p->get_program().RegisterSymbol("B"), {});
   p->register_constructed("B", &str);
 
   auto t = p->type_alias();
@@ -55,12 +55,12 @@
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t->Is<type::Alias>());
   auto* alias = t->As<type::Alias>();
-  EXPECT_EQ(p->get_module().SymbolToName(alias->symbol()), "a");
+  EXPECT_EQ(p->get_program().SymbolToName(alias->symbol()), "a");
   ASSERT_TRUE(alias->type()->Is<type::Struct>());
 
   auto* s = alias->type()->As<type::Struct>();
-  EXPECT_EQ(s->symbol(), p->get_module().RegisterSymbol("B"));
-  EXPECT_EQ(s->symbol(), p->get_module().RegisterSymbol("B"));
+  EXPECT_EQ(s->symbol(), p->get_program().RegisterSymbol("B"));
+  EXPECT_EQ(s->symbol(), p->get_program().RegisterSymbol("B"));
 }
 
 TEST_F(ParserImplTest, TypeDecl_MissingIdent) {
diff --git a/src/reader/wgsl/parser_impl_type_decl_test.cc b/src/reader/wgsl/parser_impl_type_decl_test.cc
index f82b065..4164b9f 100644
--- a/src/reader/wgsl/parser_impl_type_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_type_decl_test.cc
@@ -46,7 +46,7 @@
 TEST_F(ParserImplTest, TypeDecl_Identifier) {
   auto p = parser("A");
 
-  auto& mod = p->get_module();
+  auto& mod = p->get_program();
 
   auto* int_type = mod.create<type::I32>();
   auto* alias_type = mod.create<type::Alias>(mod.RegisterSymbol("A"), int_type);
@@ -61,7 +61,7 @@
   ASSERT_TRUE(t->Is<type::Alias>());
 
   auto* alias = t->As<type::Alias>();
-  EXPECT_EQ(p->get_module().SymbolToName(alias->symbol()), "A");
+  EXPECT_EQ(p->get_program().SymbolToName(alias->symbol()), "A");
   EXPECT_EQ(alias->type(), int_type);
 }
 
@@ -79,7 +79,7 @@
 TEST_F(ParserImplTest, TypeDecl_Bool) {
   auto p = parser("bool");
 
-  auto& mod = p->get_module();
+  auto& mod = p->get_program();
   auto* bool_type = mod.create<type::Bool>();
 
   auto t = p->type_decl();
@@ -93,7 +93,7 @@
 TEST_F(ParserImplTest, TypeDecl_F32) {
   auto p = parser("f32");
 
-  auto& mod = p->get_module();
+  auto& mod = p->get_program();
   auto* float_type = mod.create<type::F32>();
 
   auto t = p->type_decl();
@@ -107,7 +107,7 @@
 TEST_F(ParserImplTest, TypeDecl_I32) {
   auto p = parser("i32");
 
-  auto& mod = p->get_module();
+  auto& mod = p->get_program();
   auto* int_type = mod.create<type::I32>();
 
   auto t = p->type_decl();
@@ -121,7 +121,7 @@
 TEST_F(ParserImplTest, TypeDecl_U32) {
   auto p = parser("u32");
 
-  auto& mod = p->get_module();
+  auto& mod = p->get_program();
   auto* uint_type = mod.create<type::U32>();
 
   auto t = p->type_decl();
@@ -738,7 +738,7 @@
 TEST_F(ParserImplTest, TypeDecl_Sampler) {
   auto p = parser("sampler");
 
-  auto& mod = p->get_module();
+  auto& mod = p->get_program();
   auto* type = mod.create<type::Sampler>(type::SamplerKind::kSampler);
 
   auto t = p->type_decl();
@@ -753,7 +753,7 @@
 TEST_F(ParserImplTest, TypeDecl_Texture_Old) {
   auto p = parser("texture_sampled_cube<f32>");
 
-  auto& mod = p->get_module();
+  auto& mod = p->get_program();
   auto* type =
       mod.create<type::SampledTexture>(type::TextureDimension::kCube, ty.f32);
 
@@ -770,7 +770,7 @@
 TEST_F(ParserImplTest, TypeDecl_Texture) {
   auto p = parser("texture_cube<f32>");
 
-  auto& mod = p->get_module();
+  auto& mod = p->get_program();
   auto* type =
       mod.create<type::SampledTexture>(type::TextureDimension::kCube, ty.f32);
 
diff --git a/src/reader/wgsl/parser_impl_unary_expression_test.cc b/src/reader/wgsl/parser_impl_unary_expression_test.cc
index 70a1098..c1f4f34 100644
--- a/src/reader/wgsl/parser_impl_unary_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_unary_expression_test.cc
@@ -38,7 +38,7 @@
   auto* ary = e->As<ast::ArrayAccessorExpression>();
   ASSERT_TRUE(ary->array()->Is<ast::IdentifierExpression>());
   auto* ident = ary->array()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(ident->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_TRUE(ary->idx_expr()->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(ary->idx_expr()->Is<ast::ScalarConstructorExpression>());
diff --git a/src/reader/wgsl/parser_impl_variable_stmt_test.cc b/src/reader/wgsl/parser_impl_variable_stmt_test.cc
index 1a4aeba..223c9dc 100644
--- a/src/reader/wgsl/parser_impl_variable_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_variable_stmt_test.cc
@@ -32,7 +32,7 @@
   ASSERT_NE(e.value, nullptr);
   ASSERT_TRUE(e->Is<ast::VariableDeclStatement>());
   ASSERT_NE(e->variable(), nullptr);
-  EXPECT_EQ(e->variable()->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(e->variable()->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_EQ(e->source().range.begin.line, 1u);
   ASSERT_EQ(e->source().range.begin.column, 5u);
@@ -51,7 +51,7 @@
   ASSERT_NE(e.value, nullptr);
   ASSERT_TRUE(e->Is<ast::VariableDeclStatement>());
   ASSERT_NE(e->variable(), nullptr);
-  EXPECT_EQ(e->variable()->symbol(), p->get_module().RegisterSymbol("a"));
+  EXPECT_EQ(e->variable()->symbol(), p->get_program().RegisterSymbol("a"));
 
   ASSERT_EQ(e->source().range.begin.line, 1u);
   ASSERT_EQ(e->source().range.begin.column, 5u);
diff --git a/src/reader/wgsl/parser_test.cc b/src/reader/wgsl/parser_test.cc
index c4b2fe7..54031cf 100644
--- a/src/reader/wgsl/parser_test.cc
+++ b/src/reader/wgsl/parser_test.cc
@@ -41,7 +41,7 @@
   Parser p(&file);
   ASSERT_TRUE(p.Parse()) << p.error();
 
-  auto m = p.module();
+  auto m = p.program();
   ASSERT_EQ(1u, m.Functions().size());
   ASSERT_EQ(1u, m.global_variables().size());
 }
diff --git a/src/scope_stack_test.cc b/src/scope_stack_test.cc
index f5c9f84..9d45252 100644
--- a/src/scope_stack_test.cc
+++ b/src/scope_stack_test.cc
@@ -22,7 +22,7 @@
 namespace tint {
 namespace {
 
-class ScopeStackTest : public ast::BuilderWithModule, public testing::Test {};
+class ScopeStackTest : public ast::BuilderWithProgram, public testing::Test {};
 
 TEST_F(ScopeStackTest, Global) {
   ScopeStack<uint32_t> s;
diff --git a/src/transform/bound_array_accessors.cc b/src/transform/bound_array_accessors.cc
index f94a953..271c575 100644
--- a/src/transform/bound_array_accessors.cc
+++ b/src/transform/bound_array_accessors.cc
@@ -55,9 +55,9 @@
 BoundArrayAccessors::BoundArrayAccessors() = default;
 BoundArrayAccessors::~BoundArrayAccessors() = default;
 
-Transform::Output BoundArrayAccessors::Run(ast::Module* in) {
+Transform::Output BoundArrayAccessors::Run(const Program* in) {
   Output out;
-  CloneContext(&out.module, in)
+  CloneContext(&out.program, in)
       .ReplaceAll([&](CloneContext* ctx, ast::ArrayAccessorExpression* expr) {
         return Transform(expr, ctx, &out.diagnostics);
       })
diff --git a/src/transform/bound_array_accessors.h b/src/transform/bound_array_accessors.h
index 0d78df1..7c97a8b 100644
--- a/src/transform/bound_array_accessors.h
+++ b/src/transform/bound_array_accessors.h
@@ -19,8 +19,8 @@
 
 #include "src/ast/array_accessor_expression.h"
 #include "src/ast/expression.h"
-#include "src/ast/module.h"
 #include "src/ast/statement.h"
+#include "src/program.h"
 #include "src/scope_stack.h"
 #include "src/transform/transform.h"
 
@@ -38,13 +38,13 @@
   /// Destructor
   ~BoundArrayAccessors() override;
 
-  /// Runs the transform on `module`, returning the transformation result.
+  /// Runs the transform on `program`, returning the transformation result.
   /// @note Users of Tint should register the transform with transform manager
   /// and invoke its Run(), instead of directly calling the transform's Run().
-  /// Calling Run() directly does not perform module state cleanup operations.
-  /// @param module the source module to transform
+  /// Calling Run() directly does not perform program state cleanup operations.
+  /// @param program the source program to transform
   /// @returns the transformation result
-  Output Run(ast::Module* module) override;
+  Output Run(const Program* program) override;
 
  private:
   ast::ArrayAccessorExpression* Transform(ast::ArrayAccessorExpression* expr,
diff --git a/src/transform/emit_vertex_point_size.cc b/src/transform/emit_vertex_point_size.cc
index 79dd09b..3c91f79 100644
--- a/src/transform/emit_vertex_point_size.cc
+++ b/src/transform/emit_vertex_point_size.cc
@@ -38,42 +38,42 @@
 EmitVertexPointSize::EmitVertexPointSize() = default;
 EmitVertexPointSize::~EmitVertexPointSize() = default;
 
-Transform::Output EmitVertexPointSize::Run(ast::Module* in) {
+Transform::Output EmitVertexPointSize::Run(const Program* in) {
   Output out;
 
   if (!in->Functions().HasStage(ast::PipelineStage::kVertex)) {
     // If the module doesn't have any vertex stages, then there's nothing to do.
-    out.module = in->Clone();
+    out.program = in->Clone();
     return out;
   }
 
-  auto* f32 = out.module.create<type::F32>();
+  auto* f32 = out.program.create<type::F32>();
 
   // Declare the pointsize builtin output variable.
-  auto* pointsize_var = out.module.create<ast::Variable>(
-      Source{},                                  // source
-      out.module.RegisterSymbol(kPointSizeVar),  // symbol
-      ast::StorageClass::kOutput,                // storage_class
-      f32,                                       // type
-      false,                                     // is_const
-      nullptr,                                   // constructor
+  auto* pointsize_var = out.program.create<ast::Variable>(
+      Source{},                                   // source
+      out.program.RegisterSymbol(kPointSizeVar),  // symbol
+      ast::StorageClass::kOutput,                 // storage_class
+      f32,                                        // type
+      false,                                      // is_const
+      nullptr,                                    // constructor
       ast::VariableDecorationList{
           // decorations
-          out.module.create<ast::BuiltinDecoration>(Source{},
-                                                    ast::Builtin::kPointSize),
+          out.program.create<ast::BuiltinDecoration>(Source{},
+                                                     ast::Builtin::kPointSize),
       });
-  out.module.AddGlobalVariable(pointsize_var);
+  out.program.AddGlobalVariable(pointsize_var);
 
   // Build the AST expression & statement for assigning pointsize one.
-  auto* one = out.module.create<ast::ScalarConstructorExpression>(
-      Source{}, out.module.create<ast::FloatLiteral>(Source{}, f32, 1.0f));
-  auto* pointsize_ident = out.module.create<ast::IdentifierExpression>(
-      Source{}, out.module.RegisterSymbol(kPointSizeVar));
-  auto* pointsize_assign = out.module.create<ast::AssignmentStatement>(
+  auto* one = out.program.create<ast::ScalarConstructorExpression>(
+      Source{}, out.program.create<ast::FloatLiteral>(Source{}, f32, 1.0f));
+  auto* pointsize_ident = out.program.create<ast::IdentifierExpression>(
+      Source{}, out.program.RegisterSymbol(kPointSizeVar));
+  auto* pointsize_assign = out.program.create<ast::AssignmentStatement>(
       Source{}, pointsize_ident, one);
 
   // Add the pointsize assignment statement to the front of all vertex stages.
-  CloneContext(&out.module, in)
+  CloneContext(&out.program, in)
       .ReplaceAll(
           [&](CloneContext* ctx, ast::Function* func) -> ast::Function* {
             if (func->pipeline_stage() != ast::PipelineStage::kVertex) {
diff --git a/src/transform/emit_vertex_point_size.h b/src/transform/emit_vertex_point_size.h
index fc48002..edd07fa 100644
--- a/src/transform/emit_vertex_point_size.h
+++ b/src/transform/emit_vertex_point_size.h
@@ -21,10 +21,10 @@
 namespace transform {
 
 /// EmitVertexPointSize is a Transform that adds a PointSize builtin global
-/// output variable to the module which is assigned 1.0 as the new first
+/// output variable to the program which is assigned 1.0 as the new first
 /// statement for all vertex stage entry points.
-/// If the module does not contain a vertex pipeline stage entry point then then
-/// this transform is a no-op.
+/// If the program does not contain a vertex pipeline stage entry point then
+/// then this transform is a no-op.
 class EmitVertexPointSize : public Transform {
  public:
   /// Constructor
@@ -32,13 +32,13 @@
   /// Destructor
   ~EmitVertexPointSize() override;
 
-  /// Runs the transform on `module`, returning the transformation result.
+  /// Runs the transform on `program`, returning the transformation result.
   /// @note Users of Tint should register the transform with transform manager
   /// and invoke its Run(), instead of directly calling the transform's Run().
-  /// Calling Run() directly does not perform module state cleanup operations.
-  /// @param module the source module to transform
+  /// Calling Run() directly does not perform program state cleanup operations.
+  /// @param program the source program to transform
   /// @returns the transformation result
-  Output Run(ast::Module* module) override;
+  Output Run(const Program* program) override;
 };
 
 }  // namespace transform
diff --git a/src/transform/first_index_offset.cc b/src/transform/first_index_offset.cc
index b2946f07..5c6e184 100644
--- a/src/transform/first_index_offset.cc
+++ b/src/transform/first_index_offset.cc
@@ -81,11 +81,11 @@
 
 FirstIndexOffset::~FirstIndexOffset() = default;
 
-Transform::Output FirstIndexOffset::Run(ast::Module* in) {
+Transform::Output FirstIndexOffset::Run(const Program* in) {
   // First do a quick check to see if the transform has already been applied.
   for (ast::Variable* var : in->global_variables()) {
     if (auto* dec_var = var->As<ast::Variable>()) {
-      if (dec_var->symbol() == in->RegisterSymbol(kBufferName)) {
+      if (dec_var->symbol() == in->GetSymbol(kBufferName)) {
         diag::Diagnostic err;
         err.message = "First index offset transform has already been applied.";
         err.severity = diag::Severity::Error;
@@ -99,7 +99,8 @@
   // Running TypeDeterminer as we require local_referenced_builtin_variables()
   // to be populated. TODO(bclayton) - it should not be necessary to re-run the
   // type determiner if semantic information is already generated. Remove.
-  TypeDeterminer td(in);
+  // TODO(https://crbug.com/tint/390): Remove this const_cast hack!
+  TypeDeterminer td(const_cast<Program*>(in));
   if (!td.Determine()) {
     diag::Diagnostic err;
     err.severity = diag::Severity::Error;
@@ -115,9 +116,9 @@
   // Lazilly construct the UniformBuffer on first call to
   // maybe_create_buffer_var()
   ast::Variable* buffer_var = nullptr;
-  auto maybe_create_buffer_var = [&](ast::Module* mod) {
+  auto maybe_create_buffer_var = [&](Program* program) {
     if (buffer_var == nullptr) {
-      buffer_var = AddUniformBuffer(mod);
+      buffer_var = AddUniformBuffer(program);
     }
   };
 
@@ -126,7 +127,7 @@
   // these builtins.
 
   Output out;
-  CloneContext(&out.module, in)
+  CloneContext(&out.program, in)
       .ReplaceAll([&](CloneContext* ctx, ast::Variable* var) -> ast::Variable* {
         for (ast::VariableDecoration* dec : var->decorations()) {
           if (auto* blt_dec = dec->As<ast::BuiltinDecoration>()) {
@@ -194,16 +195,16 @@
   return instance_index_offset_;
 }
 
-ast::Variable* FirstIndexOffset::AddUniformBuffer(ast::Module* mod) {
-  auto* u32_type = mod->create<type::U32>();
+ast::Variable* FirstIndexOffset::AddUniformBuffer(Program* dst) {
+  auto* u32_type = dst->create<type::U32>();
   ast::StructMemberList members;
   uint32_t offset = 0;
   if (has_vertex_index_) {
     ast::StructMemberDecorationList member_dec;
     member_dec.push_back(
-        mod->create<ast::StructMemberOffsetDecoration>(Source{}, offset));
-    members.push_back(mod->create<ast::StructMember>(
-        Source{}, mod->RegisterSymbol(kFirstVertexName), u32_type,
+        dst->create<ast::StructMemberOffsetDecoration>(Source{}, offset));
+    members.push_back(dst->create<ast::StructMember>(
+        Source{}, dst->RegisterSymbol(kFirstVertexName), u32_type,
         std::move(member_dec)));
     vertex_index_offset_ = offset;
     offset += 4;
@@ -212,36 +213,36 @@
   if (has_instance_index_) {
     ast::StructMemberDecorationList member_dec;
     member_dec.push_back(
-        mod->create<ast::StructMemberOffsetDecoration>(Source{}, offset));
-    members.push_back(mod->create<ast::StructMember>(
-        Source{}, mod->RegisterSymbol(kFirstInstanceName), u32_type,
+        dst->create<ast::StructMemberOffsetDecoration>(Source{}, offset));
+    members.push_back(dst->create<ast::StructMember>(
+        Source{}, dst->RegisterSymbol(kFirstInstanceName), u32_type,
         std::move(member_dec)));
     instance_index_offset_ = offset;
     offset += 4;
   }
 
   ast::StructDecorationList decos;
-  decos.push_back(mod->create<ast::StructBlockDecoration>(Source{}));
+  decos.push_back(dst->create<ast::StructBlockDecoration>(Source{}));
 
-  auto* struct_type = mod->create<type::Struct>(
-      mod->RegisterSymbol(kStructName),
-      mod->create<ast::Struct>(Source{}, std::move(members), std::move(decos)));
+  auto* struct_type = dst->create<type::Struct>(
+      dst->RegisterSymbol(kStructName),
+      dst->create<ast::Struct>(Source{}, std::move(members), std::move(decos)));
 
-  auto* idx_var = mod->create<ast::Variable>(
+  auto* idx_var = dst->create<ast::Variable>(
       Source{},                          // source
-      mod->RegisterSymbol(kBufferName),  // symbol
+      dst->RegisterSymbol(kBufferName),  // symbol
       ast::StorageClass::kUniform,       // storage_class
       struct_type,                       // type
       false,                             // is_const
       nullptr,                           // constructor
       ast::VariableDecorationList{
-          mod->create<ast::BindingDecoration>(Source{}, binding_),
-          mod->create<ast::GroupDecoration>(Source{}, group_),
+          dst->create<ast::BindingDecoration>(Source{}, binding_),
+          dst->create<ast::GroupDecoration>(Source{}, group_),
       });  // decorations
 
-  mod->AddGlobalVariable(idx_var);
+  dst->AddGlobalVariable(idx_var);
 
-  mod->AddConstructedType(struct_type);
+  dst->AddConstructedType(struct_type);
 
   return idx_var;
 }
@@ -250,28 +251,28 @@
     const std::string& original_name,
     const std::string& field_name,
     ast::Variable* buffer_var,
-    ast::Module* mod) {
+    Program* dst) {
   auto* buffer =
-      mod->create<ast::IdentifierExpression>(Source{}, buffer_var->symbol());
+      dst->create<ast::IdentifierExpression>(Source{}, buffer_var->symbol());
 
   auto lhs_name = kIndexOffsetPrefix + original_name;
-  auto* constructor = mod->create<ast::BinaryExpression>(
+  auto* constructor = dst->create<ast::BinaryExpression>(
       Source{}, ast::BinaryOp::kAdd,
-      mod->create<ast::IdentifierExpression>(Source{},
-                                             mod->RegisterSymbol(lhs_name)),
-      mod->create<ast::MemberAccessorExpression>(
+      dst->create<ast::IdentifierExpression>(Source{},
+                                             dst->RegisterSymbol(lhs_name)),
+      dst->create<ast::MemberAccessorExpression>(
           Source{}, buffer,
-          mod->create<ast::IdentifierExpression>(
-              Source{}, mod->RegisterSymbol(field_name))));
+          dst->create<ast::IdentifierExpression>(
+              Source{}, dst->RegisterSymbol(field_name))));
   auto* var =
-      mod->create<ast::Variable>(Source{},                            // source
-                                 mod->RegisterSymbol(original_name),  // symbol
+      dst->create<ast::Variable>(Source{},                            // source
+                                 dst->RegisterSymbol(original_name),  // symbol
                                  ast::StorageClass::kNone,  // storage_class
-                                 mod->create<type::U32>(),  // type
+                                 dst->create<type::U32>(),  // type
                                  true,                      // is_const
                                  constructor,               // constructor
                                  ast::VariableDecorationList{});  // decorations
-  return mod->create<ast::VariableDeclStatement>(Source{}, var);
+  return dst->create<ast::VariableDeclStatement>(Source{}, var);
 }
 
 }  // namespace transform
diff --git a/src/transform/first_index_offset.h b/src/transform/first_index_offset.h
index 7a6e7f8..b540ca8 100644
--- a/src/transform/first_index_offset.h
+++ b/src/transform/first_index_offset.h
@@ -17,8 +17,8 @@
 
 #include <string>
 
-#include "src/ast/module.h"
 #include "src/ast/variable_decl_statement.h"
+#include "src/program.h"
 #include "src/symbol.h"
 #include "src/transform/transform.h"
 
@@ -68,13 +68,13 @@
   FirstIndexOffset(uint32_t binding, uint32_t group);
   ~FirstIndexOffset() override;
 
-  /// Runs the transform on `module`, returning the transformation result.
+  /// Runs the transform on `program`, returning the transformation result.
   /// @note Users of Tint should register the transform with transform manager
   /// and invoke its Run(), instead of directly calling the transform's Run().
-  /// Calling Run() directly does not perform module state cleanup operations.
-  /// @param module the source module to transform
+  /// Calling Run() directly does not perform program state cleanup operations.
+  /// @param program the source program to transform
   /// @returns the transformation result
-  Output Run(ast::Module* module) override;
+  Output Run(const Program* program) override;
 
   /// @returns whether shader uses vertex_index
   bool HasVertexIndex();
@@ -89,19 +89,19 @@
   uint32_t GetFirstInstanceOffset();
 
  private:
-  /// Adds uniform buffer with firstVertex/Instance to module
+  /// Adds uniform buffer with firstVertex/Instance to `program`
   /// @returns variable of new uniform buffer
-  ast::Variable* AddUniformBuffer(ast::Module* mod);
+  ast::Variable* AddUniformBuffer(Program* program);
   /// Adds constant with modified original_name builtin to func
   /// @param original_name the name of the original builtin used in function
   /// @param field_name name of field in firstVertex/Instance buffer
   /// @param buffer_var variable of firstVertex/Instance buffer
-  /// @param module the target module to contain the new ast nodes
+  /// @param program the target program to contain the new ast nodes
   ast::VariableDeclStatement* CreateFirstIndexOffset(
       const std::string& original_name,
       const std::string& field_name,
       ast::Variable* buffer_var,
-      ast::Module* module);
+      Program* program);
 
   uint32_t binding_;
   uint32_t group_;
diff --git a/src/transform/manager.cc b/src/transform/manager.cc
index 7ba0fb7..1503d62 100644
--- a/src/transform/manager.cc
+++ b/src/transform/manager.cc
@@ -22,23 +22,23 @@
 Manager::Manager() = default;
 Manager::~Manager() = default;
 
-Transform::Output Manager::Run(ast::Module* module) {
+Transform::Output Manager::Run(const Program* program) {
   Output out;
   if (!transforms_.empty()) {
     for (auto& transform : transforms_) {
-      auto res = transform->Run(module);
-      out.module = std::move(res.module);
+      auto res = transform->Run(program);
+      out.program = std::move(res.program);
       out.diagnostics.add(std::move(res.diagnostics));
       if (out.diagnostics.contains_errors()) {
         return out;
       }
-      module = &out.module;
+      program = &out.program;
     }
   } else {
-    out.module = module->Clone();
+    out.program = program->Clone();
   }
 
-  TypeDeterminer td(&out.module);
+  TypeDeterminer td(&out.program);
   if (!td.Determine()) {
     diag::Diagnostic err;
     err.severity = diag::Severity::Error;
diff --git a/src/transform/manager.h b/src/transform/manager.h
index 8f838e4..0816ce0 100644
--- a/src/transform/manager.h
+++ b/src/transform/manager.h
@@ -41,18 +41,10 @@
     transforms_.push_back(std::move(transform));
   }
 
-  /// Runs the transforms on `module`, returning the transformation result.
-  /// @param module the source module to transform
-  /// @returns the transformed module and diagnostics
-  Output Run(ast::Module* module) override;
-
-  /// Runs the transform on `program`, returning the transformation result.
-  /// @note Users of Tint should register the transform with transform manager
-  /// and invoke its Run(), instead of directly calling the transform's Run().
-  /// Calling Run() directly does not perform program state cleanup operations.
+  /// Runs the transforms on `program`, returning the transformation result.
   /// @param program the source program to transform
-  /// @returns the transformation result
-  Output Run(Program* program) { return Run(&program->module); }
+  /// @returns the transformed program and diagnostics
+  Output Run(const Program* program) override;
 
  private:
   std::vector<std::unique_ptr<Transform>> transforms_;
diff --git a/src/transform/test_helper.h b/src/transform/test_helper.h
index 73a90f8..74d6a7e 100644
--- a/src/transform/test_helper.h
+++ b/src/transform/test_helper.h
@@ -46,8 +46,8 @@
       return "WGSL reader failed:\n" + parser.error();
     }
 
-    auto module = parser.module();
-    TypeDeterminer td(&module);
+    auto program = parser.program();
+    TypeDeterminer td(&program);
     if (!td.Determine()) {
       return "Type determination failed:\n" + td.error();
     }
@@ -56,7 +56,7 @@
     for (auto& transform : transforms) {
       manager.append(std::move(transform));
     }
-    auto result = manager.Run(&module);
+    auto result = manager.Run(&program);
 
     if (result.diagnostics.contains_errors()) {
       diag::Formatter::Style style;
@@ -65,10 +65,10 @@
              diag::Formatter(style).format(result.diagnostics);
     }
 
-    // Release the source module to ensure there's no uncloned data in result
-    { auto tmp = std::move(module); }
+    // Release the source program to ensure there's no uncloned data in result
+    { auto tmp = std::move(program); }
 
-    writer::wgsl::Generator generator(std::move(result.module));
+    writer::wgsl::Generator generator(&result.program);
     if (!generator.Generate()) {
       return "WGSL writer failed:\n" + generator.error();
     }
diff --git a/src/transform/transform.cc b/src/transform/transform.cc
index 9daa763..63bf604 100644
--- a/src/transform/transform.cc
+++ b/src/transform/transform.cc
@@ -23,22 +23,16 @@
 
 Transform::Output::Output() = default;
 
-Transform::Output::Output(ast::Module&& mod) : program{std::move(mod)} {}
+Transform::Output::Output(Program&& p) : program(std::move(p)) {}
 
-Transform::Output::Output(ast::Module&& mod, diag::List&& d)
-    : program{std::move(mod)}, diagnostics(std::move(d)) {}
+Transform::Output::Output(Program&& p, diag::List&& d)
+    : program(std::move(p)), diagnostics(std::move(d)) {}
 
 Transform::Output::~Output() = default;
 
-Transform::Output::Output(Output&& rhs)
-    : program(std::move(rhs.program)),
-      diagnostics(std::move(rhs.diagnostics)) {}
+Transform::Output::Output(Output&&) = default;
 
-Transform::Output& Transform::Output::operator=(Output&& rhs) {
-  program = std::move(rhs.program);
-  diagnostics = std::move(rhs.diagnostics);
-  return *this;
-}
+Transform::Output& Transform::Output::operator=(Output&& rhs) = default;
 
 Transform::Transform() = default;
 
diff --git a/src/transform/transform.h b/src/transform/transform.h
index 9c359f2..9f00ec0 100644
--- a/src/transform/transform.h
+++ b/src/transform/transform.h
@@ -19,14 +19,13 @@
 #include <string>
 #include <utility>
 
-#include "src/ast/module.h"
 #include "src/diagnostic/diagnostic.h"
 #include "src/program.h"
 
 namespace tint {
 namespace transform {
 
-/// Interface for ast::Module transforms
+/// Interface for Program transforms
 class Transform {
  public:
   /// Constructor
@@ -40,13 +39,13 @@
     Output();
 
     /// Constructor
-    /// @param module the module to move into this Output
-    explicit Output(ast::Module&& module);
+    /// @param program the program to move into this Output
+    explicit Output(Program&& program);
 
     /// Constructor
-    /// @param module the module to move into this Output
+    /// @param program the program to move into this Output
     /// @param diags the list of diagnostics to move into this Output
-    Output(ast::Module&& module, diag::List&& diags);
+    Output(Program&& program, diag::List&& diags);
 
     /// Move constructor
     /// @param output the output to move into this Output
@@ -64,25 +63,15 @@
     Program program;
     /// Diagnostics raised while running the Transform.
     diag::List diagnostics;
-    /// The transformed module. May be empty on error.
-    ast::Module& module{program.module};
   };
 
-  /// Runs the transform on `module`, returning the transformation result.
-  /// @note Users of Tint should register the transform with transform manager
-  /// and invoke its Run(), instead of directly calling the transform's Run().
-  /// Calling Run() directly does not perform module state cleanup operations.
-  /// @param module the source module to transform
-  /// @returns the transformation result
-  virtual Output Run(ast::Module* module) = 0;
-
   /// Runs the transform on `program`, returning the transformation result.
   /// @note Users of Tint should register the transform with transform manager
   /// and invoke its Run(), instead of directly calling the transform's Run().
   /// Calling Run() directly does not perform program state cleanup operations.
   /// @param program the source program to transform
   /// @returns the transformation result
-  Output Run(Program* program) { return Run(&program->module); }
+  virtual Output Run(const Program* program) = 0;
 
  protected:
   /// Clones the function `in` adding `statements` to the beginning of the
diff --git a/src/transform/vertex_pulling.cc b/src/transform/vertex_pulling.cc
index 8a17e7b..2915a02 100644
--- a/src/transform/vertex_pulling.cc
+++ b/src/transform/vertex_pulling.cc
@@ -73,7 +73,7 @@
   cfg.pulling_group = number;
 }
 
-Transform::Output VertexPulling::Run(ast::Module* in) {
+Transform::Output VertexPulling::Run(const Program* in) {
   // Check SetVertexState was called
   if (!cfg.vertex_state_set) {
     diag::Diagnostic err;
@@ -103,13 +103,13 @@
   // following stages will pass
   Output out;
 
-  State state{in, &out.module, cfg};
+  State state{in, &out.program, cfg};
   state.FindOrInsertVertexIndexIfUsed();
   state.FindOrInsertInstanceIndexIfUsed();
   state.ConvertVertexInputVariablesToPrivate();
   state.AddVertexStorageBuffers();
 
-  CloneContext(&out.module, in)
+  CloneContext(&out.program, in)
       .ReplaceAll([&](CloneContext* ctx, ast::Function* f) -> ast::Function* {
         if (f == func) {
           return CloneWithStatementsAtStart(
@@ -126,7 +126,7 @@
 VertexPulling::Config::Config(const Config&) = default;
 VertexPulling::Config::~Config() = default;
 
-VertexPulling::State::State(ast::Module* i, ast::Module* o, const Config& c)
+VertexPulling::State::State(const Program* i, Program* o, const Config& c)
     : in(i), out(o), cfg(c) {}
 
 VertexPulling::State::State(const State&) = default;
@@ -231,7 +231,8 @@
 }
 
 void VertexPulling::State::ConvertVertexInputVariablesToPrivate() {
-  for (auto*& v : in->global_variables()) {
+  // TODO(https://crbug.com/tint/390): Remove this const_cast hack!
+  for (auto*& v : const_cast<Program*>(in)->global_variables()) {
     if (v->storage_class() != ast::StorageClass::kInput) {
       continue;
     }
diff --git a/src/transform/vertex_pulling.h b/src/transform/vertex_pulling.h
index 2a75cc5..7569cb7 100644
--- a/src/transform/vertex_pulling.h
+++ b/src/transform/vertex_pulling.h
@@ -22,9 +22,9 @@
 
 #include "src/ast/expression.h"
 #include "src/ast/function.h"
-#include "src/ast/module.h"
 #include "src/ast/statement.h"
 #include "src/ast/variable.h"
+#include "src/program.h"
 #include "src/transform/transform.h"
 
 namespace tint {
@@ -114,7 +114,7 @@
 /// attributes
 using VertexStateDescriptor = std::vector<VertexBufferLayoutDescriptor>;
 
-/// Converts a module to use vertex pulling
+/// Converts a program to use vertex pulling
 ///
 /// Variables which accept vertex input are var<in> with a location decoration.
 /// This transform will convert those to be assigned from storage buffers
@@ -159,13 +159,13 @@
   /// @param number the group number we will use
   void SetPullingBufferBindingGroup(uint32_t number);
 
-  /// Runs the transform on `module`, returning the transformation result.
+  /// Runs the transform on `program`, returning the transformation result.
   /// @note Users of Tint should register the transform with transform manager
   /// and invoke its Run(), instead of directly calling the transform's Run().
-  /// Calling Run() directly does not perform module state cleanup operations.
-  /// @param module the source module to transform
+  /// Calling Run() directly does not perform program state cleanup operations.
+  /// @param program the source program to transform
   /// @returns the transformation result
-  Output Run(ast::Module* module) override;
+  Output Run(const Program* program) override;
 
  private:
   struct Config {
@@ -183,7 +183,7 @@
   Config cfg;
 
   struct State {
-    State(ast::Module* in, ast::Module* out, const Config& c);
+    State(const Program* in, Program* out, const Config& c);
     explicit State(const State&);
     ~State();
 
@@ -263,8 +263,8 @@
     type::Type* GetI32Type() const;
     type::Type* GetF32Type() const;
 
-    ast::Module* const in;
-    ast::Module* const out;
+    const Program* const in;
+    Program* const out;
     Config const cfg;
 
     std::unordered_map<uint32_t, ast::Variable*> location_to_var;
diff --git a/src/type/access_control_type.cc b/src/type/access_control_type.cc
index d694d8b..5dafaa3 100644
--- a/src/type/access_control_type.cc
+++ b/src/type/access_control_type.cc
@@ -16,8 +16,8 @@
 
 #include <assert.h>
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::type::AccessControl);
 
diff --git a/src/type/alias_type.cc b/src/type/alias_type.cc
index a7253dd..0d10ad3 100644
--- a/src/type/alias_type.cc
+++ b/src/type/alias_type.cc
@@ -16,8 +16,8 @@
 
 #include <assert.h>
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::type::Alias);
 
diff --git a/src/type/array_type.cc b/src/type/array_type.cc
index 881b90b..469b4ea 100644
--- a/src/type/array_type.cc
+++ b/src/type/array_type.cc
@@ -17,9 +17,9 @@
 #include <cmath>
 #include <memory>
 
-#include "src/ast/module.h"
 #include "src/ast/stride_decoration.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 #include "src/type/vector_type.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::type::Array);
diff --git a/src/type/bool_type.cc b/src/type/bool_type.cc
index 5f4eb3b..de85009 100644
--- a/src/type/bool_type.cc
+++ b/src/type/bool_type.cc
@@ -14,8 +14,8 @@
 
 #include "src/type/bool_type.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::type::Bool);
 
diff --git a/src/type/depth_texture_type.cc b/src/type/depth_texture_type.cc
index a5b39e8..bc8e584 100644
--- a/src/type/depth_texture_type.cc
+++ b/src/type/depth_texture_type.cc
@@ -17,8 +17,8 @@
 #include <cassert>
 #include <sstream>
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::type::DepthTexture);
 
diff --git a/src/type/f32_type.cc b/src/type/f32_type.cc
index ad6ff66..c60c1eb 100644
--- a/src/type/f32_type.cc
+++ b/src/type/f32_type.cc
@@ -14,8 +14,8 @@
 
 #include "src/type/f32_type.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::type::F32);
 
diff --git a/src/type/i32_type.cc b/src/type/i32_type.cc
index cac2b56..402a8a9 100644
--- a/src/type/i32_type.cc
+++ b/src/type/i32_type.cc
@@ -14,8 +14,8 @@
 
 #include "src/type/i32_type.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::type::I32);
 
diff --git a/src/type/matrix_type.cc b/src/type/matrix_type.cc
index 9f01810..9b4d097 100644
--- a/src/type/matrix_type.cc
+++ b/src/type/matrix_type.cc
@@ -16,8 +16,8 @@
 
 #include <assert.h>
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 #include "src/type/array_type.h"
 #include "src/type/vector_type.h"
 
diff --git a/src/type/multisampled_texture_type.cc b/src/type/multisampled_texture_type.cc
index 22b4fe3..504019b 100644
--- a/src/type/multisampled_texture_type.cc
+++ b/src/type/multisampled_texture_type.cc
@@ -17,8 +17,8 @@
 #include <cassert>
 #include <sstream>
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::type::MultisampledTexture);
 
diff --git a/src/type/pointer_type.cc b/src/type/pointer_type.cc
index 825bd02..fd31228 100644
--- a/src/type/pointer_type.cc
+++ b/src/type/pointer_type.cc
@@ -14,8 +14,8 @@
 
 #include "src/type/pointer_type.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::type::Pointer);
 
diff --git a/src/type/sampled_texture_type.cc b/src/type/sampled_texture_type.cc
index 1aab1ab..119c547 100644
--- a/src/type/sampled_texture_type.cc
+++ b/src/type/sampled_texture_type.cc
@@ -17,8 +17,8 @@
 #include <cassert>
 #include <sstream>
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::type::SampledTexture);
 
diff --git a/src/type/sampler_type.cc b/src/type/sampler_type.cc
index 139bea1..60fc8ff 100644
--- a/src/type/sampler_type.cc
+++ b/src/type/sampler_type.cc
@@ -14,8 +14,8 @@
 
 #include "src/type/sampler_type.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::type::Sampler);
 
diff --git a/src/type/storage_texture_type.cc b/src/type/storage_texture_type.cc
index 9eb69f2..09afd48 100644
--- a/src/type/storage_texture_type.cc
+++ b/src/type/storage_texture_type.cc
@@ -17,8 +17,8 @@
 #include <cassert>
 #include <sstream>
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::type::StorageTexture);
 
diff --git a/src/type/struct_type.cc b/src/type/struct_type.cc
index 99ddc87..458aabf 100644
--- a/src/type/struct_type.cc
+++ b/src/type/struct_type.cc
@@ -17,8 +17,8 @@
 #include <cmath>
 #include <utility>
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 #include "src/type/alias_type.h"
 #include "src/type/array_type.h"
 #include "src/type/matrix_type.h"
diff --git a/src/type/test_helper.h b/src/type/test_helper.h
index e161d04..3a96f78 100644
--- a/src/type/test_helper.h
+++ b/src/type/test_helper.h
@@ -21,15 +21,15 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/builder.h"
-#include "src/ast/module.h"
 #include "src/demangler.h"
+#include "src/program.h"
 
 namespace tint {
 namespace type {
 
 /// Helper class for testing
 template <typename BASE>
-class TestHelperBase : public BASE, public ast::BuilderWithModule {
+class TestHelperBase : public BASE, public ast::BuilderWithProgram {
  public:
   /// Demangles the given string
   /// @param s the string to demangle
diff --git a/src/type/type.h b/src/type/type.h
index c55d10a..847f5c8 100644
--- a/src/type/type.h
+++ b/src/type/type.h
@@ -23,9 +23,7 @@
 
 // Forward declarations
 class CloneContext;
-namespace ast {
-class Module;
-}  // namespace ast
+class Program;
 
 namespace type {
 
@@ -103,12 +101,12 @@
 
   /// A helper method for cloning the `Type` `t` if it is not null.
   /// If `t` is null, then `Clone()` returns null.
-  /// @param m the module to clone `n` into
+  /// @param p the program to clone `n` into
   /// @param t the `Type` to clone (if not null)
   /// @return the cloned type
   template <typename T>
-  static T* Clone(ast::Module* m, const T* t) {
-    return (t != nullptr) ? static_cast<T*>(t->Clone(m)) : nullptr;
+  static T* Clone(Program* p, const T* t) {
+    return (t != nullptr) ? static_cast<T*>(t->Clone(p)) : nullptr;
   }
 };
 
diff --git a/src/type/u32_type.cc b/src/type/u32_type.cc
index be514fd..d98dbb6 100644
--- a/src/type/u32_type.cc
+++ b/src/type/u32_type.cc
@@ -14,8 +14,8 @@
 
 #include "src/type/u32_type.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::type::U32);
 
diff --git a/src/type/vector_type.cc b/src/type/vector_type.cc
index 624e81d..85a1683 100644
--- a/src/type/vector_type.cc
+++ b/src/type/vector_type.cc
@@ -17,8 +17,8 @@
 #include <assert.h>
 #include <cmath>
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::type::Vector);
 
diff --git a/src/type/void_type.cc b/src/type/void_type.cc
index 92a46dd..2f9b6f8 100644
--- a/src/type/void_type.cc
+++ b/src/type/void_type.cc
@@ -14,8 +14,8 @@
 
 #include "src/type/void_type.h"
 
-#include "src/ast/module.h"
 #include "src/clone_context.h"
+#include "src/program.h"
 
 TINT_INSTANTIATE_CLASS_ID(tint::type::Void);
 
diff --git a/src/type_determiner.cc b/src/type_determiner.cc
index fd4d657..2cb1535 100644
--- a/src/type_determiner.cc
+++ b/src/type_determiner.cc
@@ -59,10 +59,7 @@
 
 namespace tint {
 
-TypeDeterminer::TypeDeterminer(ast::Module* mod) : mod_(mod) {}
-
-TypeDeterminer::TypeDeterminer(Program* program)
-    : TypeDeterminer(&program->module) {}
+TypeDeterminer::TypeDeterminer(Program* program) : program_(program) {}
 
 TypeDeterminer::~TypeDeterminer() = default;
 
@@ -104,7 +101,7 @@
 
 bool TypeDeterminer::Determine() {
   std::vector<type::StorageTexture*> storage_textures;
-  for (auto& it : mod_->types()) {
+  for (auto& it : program_->types()) {
     if (auto* storage =
             it.second->UnwrapIfNeeded()->As<type::StorageTexture>()) {
       storage_textures.emplace_back(storage);
@@ -119,7 +116,7 @@
     }
   }
 
-  for (auto* var : mod_->global_variables()) {
+  for (auto* var : program_->global_variables()) {
     variable_stack_.set_global(var->symbol(), var);
 
     if (var->has_constructor()) {
@@ -129,13 +126,13 @@
     }
   }
 
-  if (!DetermineFunctions(mod_->Functions())) {
+  if (!DetermineFunctions(program_->Functions())) {
     return false;
   }
 
   // Walk over the caller to callee information and update functions with which
   // entry points call those functions.
-  for (auto* func : mod_->Functions()) {
+  for (auto* func : program_->Functions()) {
     if (!func->IsEntryPoint()) {
       continue;
     }
@@ -354,7 +351,7 @@
   } else if (auto* vec = parent_type->As<type::Vector>()) {
     ret = vec->type();
   } else if (auto* mat = parent_type->As<type::Matrix>()) {
-    ret = mod_->create<type::Vector>(mat->type(), mat->rows());
+    ret = program_->create<type::Vector>(mat->type(), mat->rows());
   } else {
     set_error(expr->source(), "invalid parent type (" +
                                   parent_type->type_name() +
@@ -364,13 +361,13 @@
 
   // If we're extracting from a pointer, we return a pointer.
   if (auto* ptr = res->As<type::Pointer>()) {
-    ret = mod_->create<type::Pointer>(ret, ptr->storage_class());
+    ret = program_->create<type::Pointer>(ret, ptr->storage_class());
   } else if (auto* arr = parent_type->As<type::Array>()) {
     if (!arr->type()->is_scalar()) {
       // If we extract a non-scalar from an array then we also get a pointer. We
       // will generate a Function storage class variable to store this
       // into.
-      ret = mod_->create<type::Pointer>(ret, ast::StorageClass::kFunction);
+      ret = program_->create<type::Pointer>(ret, ast::StorageClass::kFunction);
     }
   }
   expr->set_result_type(ret);
@@ -407,10 +404,11 @@
         caller_to_callee_[current_function_->symbol()].push_back(
             ident->symbol());
 
-        auto* callee_func = mod_->Functions().Find(ident->symbol());
+        auto* callee_func = program_->Functions().Find(ident->symbol());
         if (callee_func == nullptr) {
-          set_error(expr->source(), "unable to find called function: " +
-                                        mod_->SymbolToName(ident->symbol()));
+          set_error(expr->source(),
+                    "unable to find called function: " +
+                        program_->SymbolToName(ident->symbol()));
           return false;
         }
 
@@ -436,7 +434,7 @@
     auto func_sym = expr->func()->As<ast::IdentifierExpression>()->symbol();
     set_error(expr->source(),
               "v-0005: function must be declared before use: '" +
-                  mod_->SymbolToName(func_sym) + "'");
+                  program_->SymbolToName(func_sym) + "'");
     return false;
   }
 
@@ -523,7 +521,7 @@
   if (ast::intrinsic::IsDerivative(ident->intrinsic())) {
     if (expr->params().size() != 1) {
       set_error(expr->source(), "incorrect number of parameters for " +
-                                    mod_->SymbolToName(ident->symbol()));
+                                    program_->SymbolToName(ident->symbol()));
       return false;
     }
 
@@ -534,26 +532,26 @@
   }
   if (ident->intrinsic() == ast::Intrinsic::kAny ||
       ident->intrinsic() == ast::Intrinsic::kAll) {
-    expr->func()->set_result_type(mod_->create<type::Bool>());
+    expr->func()->set_result_type(program_->create<type::Bool>());
     return true;
   }
   if (ident->intrinsic() == ast::Intrinsic::kArrayLength) {
-    expr->func()->set_result_type(mod_->create<type::U32>());
+    expr->func()->set_result_type(program_->create<type::U32>());
     return true;
   }
   if (ast::intrinsic::IsFloatClassificationIntrinsic(ident->intrinsic())) {
     if (expr->params().size() != 1) {
       set_error(expr->source(), "incorrect number of parameters for " +
-                                    mod_->SymbolToName(ident->symbol()));
+                                    program_->SymbolToName(ident->symbol()));
       return false;
     }
 
-    auto* bool_type = mod_->create<type::Bool>();
+    auto* bool_type = program_->create<type::Bool>();
 
     auto* param_type = expr->params()[0]->result_type()->UnwrapPtrIfNeeded();
     if (auto* vec = param_type->As<type::Vector>()) {
       expr->func()->set_result_type(
-          mod_->create<type::Vector>(bool_type, vec->size()));
+          program_->create<type::Vector>(bool_type, vec->size()));
     } else {
       expr->func()->set_result_type(bool_type);
     }
@@ -565,7 +563,7 @@
     auto* texture_param = expr->params()[0];
     if (!texture_param->result_type()->UnwrapAll()->Is<type::Texture>()) {
       set_error(expr->source(), "invalid first argument for " +
-                                    mod_->SymbolToName(ident->symbol()));
+                                    program_->SymbolToName(ident->symbol()));
       return false;
     }
     type::Texture* texture =
@@ -677,7 +675,7 @@
     if (expr->params().size() != param.count) {
       set_error(expr->source(),
                 "incorrect number of parameters for " +
-                    mod_->SymbolToName(ident->symbol()) + ", got " +
+                    program_->SymbolToName(ident->symbol()) + ", got " +
                     std::to_string(expr->params().size()) + " and expected " +
                     std::to_string(param.count));
       return false;
@@ -690,7 +688,7 @@
     type::Type* return_type = nullptr;
     switch (ident->intrinsic()) {
       case ast::Intrinsic::kTextureDimensions: {
-        auto* i32 = mod_->create<type::I32>();
+        auto* i32 = program_->create<type::I32>();
         switch (texture->dim()) {
           default:
             set_error(expr->source(), "invalid texture dimensions");
@@ -701,12 +699,12 @@
             break;
           case type::TextureDimension::k2d:
           case type::TextureDimension::k2dArray:
-            return_type = mod_->create<type::Vector>(i32, 2);
+            return_type = program_->create<type::Vector>(i32, 2);
             break;
           case type::TextureDimension::k3d:
           case type::TextureDimension::kCube:
           case type::TextureDimension::kCubeArray:
-            return_type = mod_->create<type::Vector>(i32, 3);
+            return_type = program_->create<type::Vector>(i32, 3);
             break;
         }
         break;
@@ -714,14 +712,14 @@
       case ast::Intrinsic::kTextureNumLayers:
       case ast::Intrinsic::kTextureNumLevels:
       case ast::Intrinsic::kTextureNumSamples:
-        return_type = mod_->create<type::I32>();
+        return_type = program_->create<type::I32>();
         break;
       case ast::Intrinsic::kTextureStore:
-        return_type = mod_->create<type::Void>();
+        return_type = program_->create<type::Void>();
         break;
       default: {
         if (texture->Is<type::DepthTexture>()) {
-          return_type = mod_->create<type::F32>();
+          return_type = program_->create<type::F32>();
         } else {
           type::Type* type = nullptr;
           if (auto* storage = texture->As<type::StorageTexture>()) {
@@ -736,7 +734,7 @@
                       "unknown texture type for texture sampling");
             return false;
           }
-          return_type = mod_->create<type::Vector>(type, 4);
+          return_type = program_->create<type::Vector>(type, 4);
         }
       }
     }
@@ -745,13 +743,13 @@
     return true;
   }
   if (ident->intrinsic() == ast::Intrinsic::kDot) {
-    expr->func()->set_result_type(mod_->create<type::F32>());
+    expr->func()->set_result_type(program_->create<type::F32>());
     return true;
   }
   if (ident->intrinsic() == ast::Intrinsic::kSelect) {
     if (expr->params().size() != 3) {
       set_error(expr->source(), "incorrect number of parameters for " +
-                                    mod_->SymbolToName(ident->symbol()) +
+                                    program_->SymbolToName(ident->symbol()) +
                                     " expected 3 got " +
                                     std::to_string(expr->params().size()));
       return false;
@@ -771,13 +769,14 @@
     }
   }
   if (data == nullptr) {
-    error_ = "unable to find intrinsic " + mod_->SymbolToName(ident->symbol());
+    error_ =
+        "unable to find intrinsic " + program_->SymbolToName(ident->symbol());
     return false;
   }
 
   if (expr->params().size() != data->param_count) {
     set_error(expr->source(), "incorrect number of parameters for " +
-                                  mod_->SymbolToName(ident->symbol()) +
+                                  program_->SymbolToName(ident->symbol()) +
                                   ". Expected " +
                                   std::to_string(data->param_count) + " got " +
                                   std::to_string(expr->params().size()));
@@ -795,7 +794,7 @@
             !result_types.back()->is_integer_scalar_or_vector()) {
           set_error(expr->source(),
                     "incorrect type for " +
-                        mod_->SymbolToName(ident->symbol()) + ". " +
+                        program_->SymbolToName(ident->symbol()) + ". " +
                         "Requires float or int, scalar or vector values");
           return false;
         }
@@ -804,7 +803,7 @@
         if (!result_types.back()->is_float_scalar_or_vector()) {
           set_error(expr->source(),
                     "incorrect type for " +
-                        mod_->SymbolToName(ident->symbol()) + ". " +
+                        program_->SymbolToName(ident->symbol()) + ". " +
                         "Requires float scalar or float vector values");
           return false;
         }
@@ -814,34 +813,36 @@
         if (!result_types.back()->is_integer_scalar_or_vector()) {
           set_error(expr->source(),
                     "incorrect type for " +
-                        mod_->SymbolToName(ident->symbol()) + ". " +
+                        program_->SymbolToName(ident->symbol()) + ". " +
                         "Requires integer scalar or integer vector values");
           return false;
         }
         break;
       case IntrinsicDataType::kFloatVector:
         if (!result_types.back()->is_float_vector()) {
-          set_error(expr->source(), "incorrect type for " +
-                                        mod_->SymbolToName(ident->symbol()) +
-                                        ". " + "Requires float vector values");
+          set_error(expr->source(),
+                    "incorrect type for " +
+                        program_->SymbolToName(ident->symbol()) + ". " +
+                        "Requires float vector values");
           return false;
         }
         if (data->vector_size > 0 &&
             result_types.back()->As<type::Vector>()->size() !=
                 data->vector_size) {
-          set_error(expr->source(), "incorrect vector size for " +
-                                        mod_->SymbolToName(ident->symbol()) +
-                                        ". " + "Requires " +
-                                        std::to_string(data->vector_size) +
-                                        " elements");
+          set_error(expr->source(),
+                    "incorrect vector size for " +
+                        program_->SymbolToName(ident->symbol()) + ". " +
+                        "Requires " + std::to_string(data->vector_size) +
+                        " elements");
           return false;
         }
         break;
       case IntrinsicDataType::kMatrix:
         if (!result_types.back()->Is<type::Matrix>()) {
-          set_error(expr->source(), "incorrect type for " +
-                                        mod_->SymbolToName(ident->symbol()) +
-                                        ". Requires matrix value");
+          set_error(expr->source(),
+                    "incorrect type for " +
+                        program_->SymbolToName(ident->symbol()) +
+                        ". Requires matrix value");
           return false;
         }
         break;
@@ -852,7 +853,7 @@
   for (size_t i = 1; i < data->param_count; ++i) {
     if (result_types[0] != result_types[i]) {
       set_error(expr->source(), "mismatched parameter types for " +
-                                    mod_->SymbolToName(ident->symbol()));
+                                    program_->SymbolToName(ident->symbol()));
       return false;
     }
   }
@@ -903,7 +904,7 @@
       expr->set_result_type(var->type());
     } else {
       expr->set_result_type(
-          mod_->create<type::Pointer>(var->type(), var->storage_class()));
+          program_->create<type::Pointer>(var->type(), var->storage_class()));
     }
 
     set_referenced_from_function_if_needed(var, true);
@@ -919,14 +920,14 @@
   if (!SetIntrinsicIfNeeded(expr)) {
     set_error(expr->source(),
               "v-0006: identifier must be declared before use: " +
-                  mod_->SymbolToName(symbol));
+                  program_->SymbolToName(symbol));
     return false;
   }
   return true;
 }
 
 bool TypeDeterminer::SetIntrinsicIfNeeded(ast::IdentifierExpression* ident) {
-  auto name = mod_->SymbolToName(ident->symbol());
+  auto name = program_->SymbolToName(ident->symbol());
   if (name == "abs") {
     ident->set_intrinsic(ast::Intrinsic::kAbs);
   } else if (name == "acos") {
@@ -1099,32 +1100,33 @@
     }
 
     if (ret == nullptr) {
-      set_error(expr->source(),
-                "struct member " + mod_->SymbolToName(symbol) + " not found");
+      set_error(
+          expr->source(),
+          "struct member " + program_->SymbolToName(symbol) + " not found");
       return false;
     }
 
     // If we're extracting from a pointer, we return a pointer.
     if (auto* ptr = res->As<type::Pointer>()) {
-      ret = mod_->create<type::Pointer>(ret, ptr->storage_class());
+      ret = program_->create<type::Pointer>(ret, ptr->storage_class());
     }
   } else if (auto* vec = data_type->As<type::Vector>()) {
     // TODO(dsinclair): Swizzle, record into the identifier experesion
 
-    auto size = mod_->SymbolToName(expr->member()->symbol()).size();
+    auto size = program_->SymbolToName(expr->member()->symbol()).size();
     if (size == 1) {
       // A single element swizzle is just the type of the vector.
       ret = vec->type();
       // If we're extracting from a pointer, we return a pointer.
       if (auto* ptr = res->As<type::Pointer>()) {
-        ret = mod_->create<type::Pointer>(ret, ptr->storage_class());
+        ret = program_->create<type::Pointer>(ret, ptr->storage_class());
       }
     } else {
       // The vector will have a number of components equal to the length of the
       // swizzle. This assumes the validator will check that the swizzle
       // is correct.
-      ret =
-          mod_->create<type::Vector>(vec->type(), static_cast<uint32_t>(size));
+      ret = program_->create<type::Vector>(vec->type(),
+                                           static_cast<uint32_t>(size));
     }
   } else {
     set_error(
@@ -1155,10 +1157,11 @@
   if (expr->IsLogicalAnd() || expr->IsLogicalOr() || expr->IsEqual() ||
       expr->IsNotEqual() || expr->IsLessThan() || expr->IsGreaterThan() ||
       expr->IsLessThanEqual() || expr->IsGreaterThanEqual()) {
-    auto* bool_type = mod_->create<type::Bool>();
+    auto* bool_type = program_->create<type::Bool>();
     auto* param_type = expr->lhs()->result_type()->UnwrapPtrIfNeeded();
     if (auto* vec = param_type->As<type::Vector>()) {
-      expr->set_result_type(mod_->create<type::Vector>(bool_type, vec->size()));
+      expr->set_result_type(
+          program_->create<type::Vector>(bool_type, vec->size()));
     } else {
       expr->set_result_type(bool_type);
     }
@@ -1175,14 +1178,14 @@
     auto* lhs_vec = lhs_type->As<type::Vector>();
     auto* rhs_vec = rhs_type->As<type::Vector>();
     if (lhs_mat && rhs_mat) {
-      expr->set_result_type(mod_->create<type::Matrix>(
+      expr->set_result_type(program_->create<type::Matrix>(
           lhs_mat->type(), lhs_mat->rows(), rhs_mat->columns()));
     } else if (lhs_mat && rhs_vec) {
       expr->set_result_type(
-          mod_->create<type::Vector>(lhs_mat->type(), lhs_mat->rows()));
+          program_->create<type::Vector>(lhs_mat->type(), lhs_mat->rows()));
     } else if (lhs_vec && rhs_mat) {
       expr->set_result_type(
-          mod_->create<type::Vector>(rhs_mat->type(), rhs_mat->columns()));
+          program_->create<type::Vector>(rhs_mat->type(), rhs_mat->columns()));
     } else if (lhs_mat) {
       // matrix * scalar
       expr->set_result_type(lhs_type);
@@ -1233,7 +1236,7 @@
     case type::ImageFormat::kRg32Uint:
     case type::ImageFormat::kRgba16Uint:
     case type::ImageFormat::kRgba32Uint: {
-      tex->set_type(mod_->create<type::U32>());
+      tex->set_type(program_->create<type::U32>());
       return true;
     }
 
@@ -1246,7 +1249,7 @@
     case type::ImageFormat::kRg32Sint:
     case type::ImageFormat::kRgba16Sint:
     case type::ImageFormat::kRgba32Sint: {
-      tex->set_type(mod_->create<type::I32>());
+      tex->set_type(program_->create<type::I32>());
       return true;
     }
 
@@ -1267,7 +1270,7 @@
     case type::ImageFormat::kRg32Float:
     case type::ImageFormat::kRgba16Float:
     case type::ImageFormat::kRgba32Float: {
-      tex->set_type(mod_->create<type::F32>());
+      tex->set_type(program_->create<type::F32>());
       return true;
     }
 
diff --git a/src/type_determiner.h b/src/type_determiner.h
index be1e8ec..5387714 100644
--- a/src/type_determiner.h
+++ b/src/type_determiner.h
@@ -41,15 +41,11 @@
 
 }  // namespace ast
 
-/// Determines types for all items in the given tint module
+/// Determines types for all items in the given tint program
 class TypeDeterminer {
  public:
   /// Constructor
-  /// @param mod the module to update with typing information
-  explicit TypeDeterminer(ast::Module* mod);
-
-  /// Constructor
-  /// @param program the module to update with typing information
+  /// @param program the program to update with typing information
   explicit TypeDeterminer(Program* program);
 
   /// Destructor
@@ -142,7 +138,7 @@
   bool DetermineMemberAccessor(ast::MemberAccessorExpression* expr);
   bool DetermineUnaryOp(ast::UnaryOpExpression* expr);
 
-  ast::Module* mod_;
+  Program* program_;
   std::string error_;
   ScopeStack<ast::Variable*> variable_stack_;
   std::unordered_map<Symbol, ast::Function*> symbol_to_function_;
diff --git a/src/type_determiner_test.cc b/src/type_determiner_test.cc
index 5138838..068a1ce 100644
--- a/src/type_determiner_test.cc
+++ b/src/type_determiner_test.cc
@@ -87,9 +87,9 @@
   void to_str(std::ostream&, size_t) const override {}
 };
 
-class TypeDeterminerHelper : public ast::BuilderWithModule {
+class TypeDeterminerHelper : public ast::BuilderWithProgram {
  public:
-  TypeDeterminerHelper() : td_(std::make_unique<TypeDeterminer>(mod)) {}
+  TypeDeterminerHelper() : td_(std::make_unique<TypeDeterminer>(program)) {}
 
   TypeDeterminer* td() const { return td_.get(); }
 
diff --git a/src/validator/validator.cc b/src/validator/validator.cc
index 07466d9..c0e4aa8 100644
--- a/src/validator/validator.cc
+++ b/src/validator/validator.cc
@@ -22,8 +22,8 @@
 
 Validator::~Validator() = default;
 
-bool Validator::Validate(const ast::Module* module) {
-  ValidatorImpl impl(module);
+bool Validator::Validate(const Program* program) {
+  ValidatorImpl impl(program);
   bool ret = impl.Validate();
   diags_ = impl.diagnostics();
   return ret;
diff --git a/src/validator/validator.h b/src/validator/validator.h
index 9d3fbc7..65b9777 100644
--- a/src/validator/validator.h
+++ b/src/validator/validator.h
@@ -20,7 +20,6 @@
 
 #include "src/ast/assignment_statement.h"
 #include "src/ast/expression.h"
-#include "src/ast/module.h"
 #include "src/ast/statement.h"
 #include "src/diagnostic/diagnostic.h"
 #include "src/diagnostic/formatter.h"
@@ -28,7 +27,7 @@
 
 namespace tint {
 
-/// Determines if the module is complete and valid
+/// Determines if the program is complete and valid
 class Validator {
  public:
   /// Constructor
@@ -36,14 +35,9 @@
   ~Validator();
 
   /// Runs the validator
-  /// @param module the module to validate
-  /// @returns true if the validation was successful
-  bool Validate(const ast::Module* module);
-
-  /// Runs the validator
   /// @param program the program to validate
   /// @returns true if the validation was successful
-  bool Validate(const Program* program) { return Validate(&program->module); }
+  bool Validate(const Program* program);
 
   /// @returns error messages from the validator
   std::string error() {
diff --git a/src/validator/validator_impl.cc b/src/validator/validator_impl.cc
index 46831e9..73befed 100644
--- a/src/validator/validator_impl.cc
+++ b/src/validator/validator_impl.cc
@@ -40,7 +40,7 @@
 
 namespace tint {
 
-ValidatorImpl::ValidatorImpl(const ast::Module* module) : module_(*module) {}
+ValidatorImpl::ValidatorImpl(const Program* program) : program_(program) {}
 
 ValidatorImpl::~ValidatorImpl() = default;
 
@@ -65,16 +65,16 @@
 
 bool ValidatorImpl::Validate() {
   function_stack_.push_scope();
-  if (!ValidateGlobalVariables(module_.global_variables())) {
+  if (!ValidateGlobalVariables(program_->global_variables())) {
     return false;
   }
-  if (!ValidateConstructedTypes(module_.constructed_types())) {
+  if (!ValidateConstructedTypes(program_->constructed_types())) {
     return false;
   }
-  if (!ValidateFunctions(module_.Functions())) {
+  if (!ValidateFunctions(program_->Functions())) {
     return false;
   }
-  if (!ValidateEntryPoint(module_.Functions())) {
+  if (!ValidateEntryPoint(program_->Functions())) {
     return false;
   }
   function_stack_.pop_scope();
@@ -99,7 +99,7 @@
               add_error(member->source(), "v-0031",
                         "a struct containing a runtime-sized array "
                         "must be in the 'storage' storage class: '" +
-                            module_.SymbolToName(st->symbol()) + "'");
+                            program_->SymbolToName(st->symbol()) + "'");
               return false;
             }
           }
@@ -116,7 +116,7 @@
     if (variable_stack_.has(var->symbol())) {
       add_error(var->source(), "v-0011",
                 "redeclared global identifier '" +
-                    module_.SymbolToName(var->symbol()) + "'");
+                    program_->SymbolToName(var->symbol()) + "'");
       return false;
     }
     if (!var->is_const() && var->storage_class() == ast::StorageClass::kNone) {
@@ -140,7 +140,7 @@
     if (function_stack_.has(func->symbol())) {
       add_error(func->source(), "v-0016",
                 "function names must be unique '" +
-                    module_.SymbolToName(func->symbol()) + "'");
+                    program_->SymbolToName(func->symbol()) + "'");
       return false;
     }
 
@@ -163,14 +163,14 @@
       if (!func->params().empty()) {
         add_error(func->source(), "v-0023",
                   "Entry point function must accept no parameters: '" +
-                      module_.SymbolToName(func->symbol()) + "'");
+                      program_->SymbolToName(func->symbol()) + "'");
         return false;
       }
 
       if (!func->return_type()->Is<type::Void>()) {
         add_error(func->source(), "v-0024",
                   "Entry point function must return void: '" +
-                      module_.SymbolToName(func->symbol()) + "'");
+                      program_->SymbolToName(func->symbol()) + "'");
         return false;
       }
       auto stage_deco_count = 0;
@@ -275,7 +275,7 @@
       error_code = "v-0013";
     }
     add_error(decl->source(), error_code,
-              "redeclared identifier '" + module_.SymbolToName(symbol) + "'");
+              "redeclared identifier '" + program_->SymbolToName(symbol) + "'");
     return false;
   }
   // TODO(dneto): Check type compatibility of the initializer.
@@ -415,13 +415,13 @@
       if (!function_stack_.has(symbol)) {
         add_error(expr->source(), "v-0005",
                   "function must be declared before use: '" +
-                      module_.SymbolToName(symbol) + "'");
+                      program_->SymbolToName(symbol) + "'");
         return false;
       }
       if (symbol == current_function_->symbol()) {
-        add_error(
-            expr->source(), "v-0004",
-            "recursion is not allowed: '" + module_.SymbolToName(symbol) + "'");
+        add_error(expr->source(), "v-0004",
+                  "recursion is not allowed: '" +
+                      program_->SymbolToName(symbol) + "'");
         return false;
       }
     }
@@ -447,7 +447,7 @@
     if (var->is_const()) {
       add_error(assign->source(), "v-0021",
                 "cannot re-assign a constant: '" +
-                    module_.SymbolToName(ident->symbol()) + "'");
+                    program_->SymbolToName(ident->symbol()) + "'");
       return false;
     }
   } else {
@@ -455,7 +455,7 @@
     // when validating the subexpression.
     add_error(
         ident->source(), "v-0006",
-        "'" + module_.SymbolToName(ident->symbol()) + "' is not declared");
+        "'" + program_->SymbolToName(ident->symbol()) + "' is not declared");
     return false;
   }
   return true;
@@ -527,7 +527,7 @@
   if (!variable_stack_.get(ident->symbol(), &var)) {
     add_error(
         ident->source(), "v-0006",
-        "'" + module_.SymbolToName(ident->symbol()) + "' is not declared");
+        "'" + program_->SymbolToName(ident->symbol()) + "' is not declared");
     return false;
   }
   return true;
diff --git a/src/validator/validator_impl.h b/src/validator/validator_impl.h
index 58aa2e1..0ee8c05 100644
--- a/src/validator/validator_impl.h
+++ b/src/validator/validator_impl.h
@@ -24,7 +24,6 @@
 #include "src/ast/call_expression.h"
 #include "src/ast/expression.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/return_statement.h"
 #include "src/ast/statement.h"
 #include "src/ast/switch_statement.h"
@@ -32,16 +31,17 @@
 #include "src/ast/variable_decl_statement.h"
 #include "src/diagnostic/diagnostic.h"
 #include "src/diagnostic/formatter.h"
+#include "src/program.h"
 #include "src/scope_stack.h"
 
 namespace tint {
 
-/// Determines if the module is complete and valid
+/// Determines if the program is complete and valid
 class ValidatorImpl {
  public:
   /// Constructor
-  /// @param module the module to validate
-  explicit ValidatorImpl(const ast::Module* module);
+  /// @param program the program to validate
+  explicit ValidatorImpl(const Program* program);
   ~ValidatorImpl();
 
   /// Runs the validator
@@ -159,7 +159,7 @@
   }
 
  private:
-  const ast::Module& module_;
+  const Program* program_;
   diag::List diags_;
   ScopeStack<ast::Variable*> variable_stack_;
   ScopeStack<ast::Function*> function_stack_;
diff --git a/src/validator/validator_test_helper.h b/src/validator/validator_test_helper.h
index 9500e80..25a59dd 100644
--- a/src/validator/validator_test_helper.h
+++ b/src/validator/validator_test_helper.h
@@ -28,13 +28,13 @@
 namespace tint {
 
 /// A helper for testing validation
-class ValidatorTestHelper : public ast::BuilderWithModule {
+class ValidatorTestHelper : public ast::BuilderWithProgram {
  public:
   /// Constructor
   ValidatorTestHelper();
   ~ValidatorTestHelper() override;
 
-  /// Builds and returns a validator from the module.
+  /// Builds and returns a validator from the program.
   /// @note The validator is only built once. Multiple calls to Build() will
   /// return the same ValidatorImpl without rebuilding.
   /// @return the built validator
@@ -42,7 +42,7 @@
     if (val_) {
       return *val_;
     }
-    val_ = std::make_unique<ValidatorImpl>(mod);
+    val_ = std::make_unique<ValidatorImpl>(program);
     for (auto* var : vars_for_testing_) {
       val_->RegisterVariableForTesting(var);
     }
diff --git a/src/writer/hlsl/generator.cc b/src/writer/hlsl/generator.cc
index 90d78c6..15f2ee8 100644
--- a/src/writer/hlsl/generator.cc
+++ b/src/writer/hlsl/generator.cc
@@ -20,12 +20,8 @@
 namespace writer {
 namespace hlsl {
 
-Generator::Generator(ast::Module module)
-    : module_(std::move(module)),
-      impl_(std::make_unique<GeneratorImpl>(&module_)) {}
-
-Generator::Generator(Program* program)
-    : impl_(std::make_unique<GeneratorImpl>(&program->module)) {}
+Generator::Generator(const Program* program)
+    : impl_(std::make_unique<GeneratorImpl>(program)) {}
 
 Generator::~Generator() = default;
 
diff --git a/src/writer/hlsl/generator.h b/src/writer/hlsl/generator.h
index 1c3b58c..63e6c3d 100644
--- a/src/writer/hlsl/generator.h
+++ b/src/writer/hlsl/generator.h
@@ -31,12 +31,8 @@
 class Generator : public Text {
  public:
   /// Constructor
-  /// @param module the module to convert
-  explicit Generator(ast::Module module);
-
-  /// Constructor
   /// @param program the program to convert
-  explicit Generator(Program* program);
+  explicit Generator(const Program* program);
 
   /// Destructor
   ~Generator() override;
@@ -59,7 +55,6 @@
   std::string error() const;
 
  private:
-  ast::Module module_;
   std::ostringstream out_;
   std::unique_ptr<GeneratorImpl> impl_;
 };
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index 93ab2e6..6357d8f 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -125,7 +125,7 @@
 
 }  // namespace
 
-GeneratorImpl::GeneratorImpl(ast::Module* module) : module_(module) {}
+GeneratorImpl::GeneratorImpl(const Program* program) : program_(program) {}
 
 GeneratorImpl::~GeneratorImpl() = default;
 
@@ -136,20 +136,20 @@
 }
 
 bool GeneratorImpl::Generate(std::ostream& out) {
-  for (auto* global : module_->global_variables()) {
+  for (auto* global : program_->global_variables()) {
     register_global(global);
   }
 
-  for (auto* const ty : module_->constructed_types()) {
+  for (auto* const ty : program_->constructed_types()) {
     if (!EmitConstructedType(out, ty)) {
       return false;
     }
   }
-  if (!module_->constructed_types().empty()) {
+  if (!program_->constructed_types().empty()) {
     out << std::endl;
   }
 
-  for (auto* var : module_->global_variables()) {
+  for (auto* var : program_->global_variables()) {
     if (!var->is_const()) {
       continue;
     }
@@ -160,7 +160,7 @@
 
   std::unordered_set<Symbol> emitted_globals;
   // Make sure all entry point data is emitted before the entry point functions
-  for (auto* func : module_->Functions()) {
+  for (auto* func : program_->Functions()) {
     if (!func->IsEntryPoint()) {
       continue;
     }
@@ -170,13 +170,13 @@
     }
   }
 
-  for (auto* func : module_->Functions()) {
+  for (auto* func : program_->Functions()) {
     if (!EmitFunction(out, func)) {
       return false;
     }
   }
 
-  for (auto* func : module_->Functions()) {
+  for (auto* func : program_->Functions()) {
     if (!func->IsEntryPoint()) {
       continue;
     }
@@ -232,7 +232,7 @@
     // HLSL typedef is for intrinsic types only. For an alias'd struct,
     // generate a secondary struct with the new name.
     if (auto* str = alias->type()->As<type::Struct>()) {
-      if (!EmitStructType(out, str, module_->SymbolToName(alias->symbol()))) {
+      if (!EmitStructType(out, str, program_->SymbolToName(alias->symbol()))) {
         return false;
       }
       return true;
@@ -241,10 +241,10 @@
     if (!EmitType(out, alias->type(), "")) {
       return false;
     }
-    out << " " << namer_.NameFor(module_->SymbolToName(alias->symbol())) << ";"
+    out << " " << namer_.NameFor(program_->SymbolToName(alias->symbol())) << ";"
         << std::endl;
   } else if (auto* str = ty->As<type::Struct>()) {
-    if (!EmitStructType(out, str, module_->SymbolToName(str->symbol()))) {
+    if (!EmitStructType(out, str, program_->SymbolToName(str->symbol()))) {
       return false;
     }
   } else {
@@ -623,7 +623,7 @@
     return true;
   }
 
-  auto name = module_->SymbolToName(ident->symbol());
+  auto name = program_->SymbolToName(ident->symbol());
   auto caller_sym = ident->symbol();
   auto it = ep_func_name_remapped_.find(current_ep_sym_.to_str() + "_" +
                                         caller_sym.to_str());
@@ -631,10 +631,10 @@
     name = it->second;
   }
 
-  auto* func = module_->Functions().Find(ident->symbol());
+  auto* func = program_->Functions().Find(ident->symbol());
   if (func == nullptr) {
     error_ =
-        "Unable to find function: " + module_->SymbolToName(ident->symbol());
+        "Unable to find function: " + program_->SymbolToName(ident->symbol());
     return false;
   }
 
@@ -868,7 +868,7 @@
       break;
     default:
       error_ = "Internal compiler error: Unhandled texture intrinsic '" +
-               module_->SymbolToName(ident->symbol()) + "'";
+               program_->SymbolToName(ident->symbol()) + "'";
       return false;
   }
 
@@ -881,7 +881,8 @@
   auto* param_coords = params[pidx.coords];
 
   auto emit_vector_appended_with_i32_zero = [&](tint::ast::Expression* vector) {
-    auto* i32 = module_->create<type::I32>();
+    // TODO(https://crbug.com/tint/390): Remove this const_cast hack!
+    auto* i32 = const_cast<Program*>(program_)->create<type::I32>();
     ast::SintLiteral zero_lit(Source{}, i32, 0);
     ast::ScalarConstructorExpression zero(Source{}, &zero_lit);
     zero.set_result_type(i32);
@@ -971,7 +972,7 @@
     case ast::Intrinsic::kMax:
     case ast::Intrinsic::kMin:
     case ast::Intrinsic::kClamp:
-      out = module_->SymbolToName(ident->symbol());
+      out = program_->SymbolToName(ident->symbol());
       break;
     case ast::Intrinsic::kFaceForward:
       out = "faceforward";
@@ -987,7 +988,7 @@
       break;
     default:
       error_ =
-          "Unknown builtin method: " + module_->SymbolToName(ident->symbol());
+          "Unknown builtin method: " + program_->SymbolToName(ident->symbol());
       return "";
   }
 
@@ -1167,7 +1168,7 @@
       out << name << ".";
     }
   }
-  out << namer_.NameFor(module_->SymbolToName(ident->symbol()));
+  out << namer_.NameFor(program_->SymbolToName(ident->symbol()));
 
   return true;
 }
@@ -1329,12 +1330,12 @@
     auto ep_name = ep_sym.to_str();
     // TODO(dsinclair): The SymbolToName should go away and just use
     // to_str() here when the conversion is complete.
-    name = generate_name(module_->SymbolToName(func->symbol()) + "_" +
-                         module_->SymbolToName(ep_sym));
+    name = generate_name(program_->SymbolToName(func->symbol()) + "_" +
+                         program_->SymbolToName(ep_sym));
     ep_func_name_remapped_[ep_name + "_" + func_name] = name;
   } else {
     // TODO(dsinclair): this should be updated to a remapped name
-    name = namer_.NameFor(module_->SymbolToName(func->symbol()));
+    name = namer_.NameFor(program_->SymbolToName(func->symbol()));
   }
 
   out << name << "(";
@@ -1370,12 +1371,12 @@
     }
     first = false;
 
-    if (!EmitType(out, v->type(), module_->SymbolToName(v->symbol()))) {
+    if (!EmitType(out, v->type(), program_->SymbolToName(v->symbol()))) {
       return false;
     }
     // Array name is output as part of the type
     if (!v->type()->Is<type::Array>()) {
-      out << " " << module_->SymbolToName(v->symbol());
+      out << " " << program_->SymbolToName(v->symbol());
     }
   }
 
@@ -1429,7 +1430,7 @@
     auto* binding = data.second.binding;
     if (binding == nullptr) {
       error_ = "unable to find binding information for uniform: " +
-               module_->SymbolToName(var->symbol());
+               program_->SymbolToName(var->symbol());
       return false;
     }
     // auto* set = data.second.set;
@@ -1443,8 +1444,8 @@
 
     auto* type = var->type()->UnwrapIfNeeded();
     if (auto* strct = type->As<type::Struct>()) {
-      out << "ConstantBuffer<" << module_->SymbolToName(strct->symbol()) << "> "
-          << module_->SymbolToName(var->symbol()) << " : register(b"
+      out << "ConstantBuffer<" << program_->SymbolToName(strct->symbol())
+          << "> " << program_->SymbolToName(var->symbol()) << " : register(b"
           << binding->value() << ");" << std::endl;
     } else {
       // TODO(dsinclair): There is outstanding spec work to require all uniform
@@ -1453,7 +1454,7 @@
       // is not a block.
       // Relevant: https://github.com/gpuweb/gpuweb/issues/1004
       //           https://github.com/gpuweb/gpuweb/issues/1008
-      auto name = "cbuffer_" + module_->SymbolToName(var->symbol());
+      auto name = "cbuffer_" + program_->SymbolToName(var->symbol());
       out << "cbuffer " << name << " : register(b" << binding->value() << ") {"
           << std::endl;
 
@@ -1462,7 +1463,7 @@
       if (!EmitType(out, type, "")) {
         return false;
       }
-      out << " " << module_->SymbolToName(var->symbol()) << ";" << std::endl;
+      out << " " << program_->SymbolToName(var->symbol()) << ";" << std::endl;
       decrement_indent();
       out << "};" << std::endl;
     }
@@ -1494,7 +1495,7 @@
     if (ac->IsReadWrite()) {
       out << "RW";
     }
-    out << "ByteAddressBuffer " << module_->SymbolToName(var->symbol())
+    out << "ByteAddressBuffer " << program_->SymbolToName(var->symbol())
         << " : register(u" << binding->value() << ");" << std::endl;
     emitted_storagebuffer = true;
   }
@@ -1503,7 +1504,7 @@
   }
 
   if (!in_variables.empty()) {
-    auto in_struct_name = generate_name(module_->SymbolToName(func->symbol()) +
+    auto in_struct_name = generate_name(program_->SymbolToName(func->symbol()) +
                                         "_" + kInStructNameSuffix);
     auto in_var_name = generate_name(kTintStructInVarPrefix);
     ep_sym_to_in_data_[func->symbol()] = {in_struct_name, in_var_name};
@@ -1518,11 +1519,11 @@
       auto* deco = data.second;
 
       make_indent(out);
-      if (!EmitType(out, var->type(), module_->SymbolToName(var->symbol()))) {
+      if (!EmitType(out, var->type(), program_->SymbolToName(var->symbol()))) {
         return false;
       }
 
-      out << " " << module_->SymbolToName(var->symbol()) << " : ";
+      out << " " << program_->SymbolToName(var->symbol()) << " : ";
       if (auto* location = deco->As<ast::LocationDecoration>()) {
         if (func->pipeline_stage() == ast::PipelineStage::kCompute) {
           error_ = "invalid location variable for pipeline stage";
@@ -1549,7 +1550,7 @@
   }
 
   if (!outvariables.empty()) {
-    auto outstruct_name = generate_name(module_->SymbolToName(func->symbol()) +
+    auto outstruct_name = generate_name(program_->SymbolToName(func->symbol()) +
                                         "_" + kOutStructNameSuffix);
     auto outvar_name = generate_name(kTintStructOutVarPrefix);
     ep_sym_to_out_data_[func->symbol()] = {outstruct_name, outvar_name};
@@ -1563,11 +1564,11 @@
       auto* deco = data.second;
 
       make_indent(out);
-      if (!EmitType(out, var->type(), module_->SymbolToName(var->symbol()))) {
+      if (!EmitType(out, var->type(), program_->SymbolToName(var->symbol()))) {
         return false;
       }
 
-      out << " " << module_->SymbolToName(var->symbol()) << " : ";
+      out << " " << program_->SymbolToName(var->symbol()) << " : ";
 
       if (auto* location = deco->As<ast::LocationDecoration>()) {
         auto loc = location->value();
@@ -1650,7 +1651,7 @@
     out << "void";
   }
   // TODO(dsinclair): This should output the remapped name
-  out << " " << namer_.NameFor(module_->SymbolToName(current_ep_sym_)) << "(";
+  out << " " << namer_.NameFor(program_->SymbolToName(current_ep_sym_)) << "(";
 
   auto in_data = ep_sym_to_in_data_.find(current_ep_sym_);
   if (in_data != ep_sym_to_in_data_.end()) {
@@ -1798,7 +1799,7 @@
         }
         out << pre.str();
 
-        out << module_->SymbolToName(var->symbol()) << " = ";
+        out << program_->SymbolToName(var->symbol()) << " = ";
         if (var->constructor() != nullptr) {
           out << constructor_out.str();
         } else {
@@ -1861,7 +1862,7 @@
         //
         // This must be a single element swizzle if we've got a vector at this
         // point.
-        if (module_->SymbolToName(mem->member()->symbol()).size() != 1) {
+        if (program_->SymbolToName(mem->member()->symbol()).size() != 1) {
           error_ =
               "Encountered multi-element swizzle when should have only one "
               "level";
@@ -1873,7 +1874,7 @@
         // f64 types.
         out << "(4 * "
             << convert_swizzle_to_index(
-                   module_->SymbolToName(mem->member()->symbol()))
+                   program_->SymbolToName(mem->member()->symbol()))
             << ")";
       } else {
         error_ =
@@ -2052,7 +2053,7 @@
   // If the data is a multi-element swizzle then we will not load the swizzle
   // portion through the Load command.
   if (data_type->Is<type::Vector>() &&
-      module_->SymbolToName(expr->member()->symbol()).size() > 1) {
+      program_->SymbolToName(expr->member()->symbol()).size() > 1) {
     return false;
   }
 
@@ -2204,7 +2205,7 @@
   }
 
   if (auto* alias = type->As<type::Alias>()) {
-    out << namer_.NameFor(module_->SymbolToName(alias->symbol()));
+    out << namer_.NameFor(program_->SymbolToName(alias->symbol()));
   } else if (auto* ary = type->As<type::Array>()) {
     type::Type* base_type = ary;
     std::vector<uint32_t> sizes;
@@ -2251,7 +2252,7 @@
     }
     out << "State";
   } else if (auto* str = type->As<type::Struct>()) {
-    out << module_->SymbolToName(str->symbol());
+    out << program_->SymbolToName(str->symbol());
   } else if (auto* tex = type->As<type::Texture>()) {
     if (tex->Is<type::StorageTexture>()) {
       out << "RW";
@@ -2335,12 +2336,12 @@
     // TODO(dsinclair): Handle [[offset]] annotation on structs
     // https://bugs.chromium.org/p/tint/issues/detail?id=184
 
-    if (!EmitType(out, mem->type(), module_->SymbolToName(mem->symbol()))) {
+    if (!EmitType(out, mem->type(), program_->SymbolToName(mem->symbol()))) {
       return false;
     }
     // Array member name will be output with the type
     if (!mem->type()->Is<type::Array>()) {
-      out << " " << namer_.NameFor(module_->SymbolToName(mem->symbol()));
+      out << " " << namer_.NameFor(program_->SymbolToName(mem->symbol()));
     }
     out << ";" << std::endl;
   }
@@ -2399,11 +2400,11 @@
   if (var->is_const()) {
     out << "const ";
   }
-  if (!EmitType(out, var->type(), module_->SymbolToName(var->symbol()))) {
+  if (!EmitType(out, var->type(), program_->SymbolToName(var->symbol()))) {
     return false;
   }
   if (!var->type()->Is<type::Array>()) {
-    out << " " << module_->SymbolToName(var->symbol());
+    out << " " << program_->SymbolToName(var->symbol());
   }
   out << constructor_out.str() << ";" << std::endl;
 
@@ -2448,19 +2449,19 @@
     }
     out << "#endif" << std::endl;
     out << "static const ";
-    if (!EmitType(out, var->type(), module_->SymbolToName(var->symbol()))) {
+    if (!EmitType(out, var->type(), program_->SymbolToName(var->symbol()))) {
       return false;
     }
-    out << " " << module_->SymbolToName(var->symbol())
+    out << " " << program_->SymbolToName(var->symbol())
         << " = WGSL_SPEC_CONSTANT_" << const_id << ";" << std::endl;
     out << "#undef WGSL_SPEC_CONSTANT_" << const_id << std::endl;
   } else {
     out << "static const ";
-    if (!EmitType(out, var->type(), module_->SymbolToName(var->symbol()))) {
+    if (!EmitType(out, var->type(), program_->SymbolToName(var->symbol()))) {
       return false;
     }
     if (!var->type()->Is<type::Array>()) {
-      out << " " << module_->SymbolToName(var->symbol());
+      out << " " << program_->SymbolToName(var->symbol());
     }
 
     if (var->constructor() != nullptr) {
@@ -2475,7 +2476,7 @@
 std::string GeneratorImpl::get_buffer_name(ast::Expression* expr) {
   for (;;) {
     if (auto* ident = expr->As<ast::IdentifierExpression>()) {
-      return module_->SymbolToName(ident->symbol());
+      return program_->SymbolToName(ident->symbol());
     } else if (auto* member = expr->As<ast::MemberAccessorExpression>()) {
       expr = member->structure();
     } else if (auto* array = expr->As<ast::ArrayAccessorExpression>()) {
diff --git a/src/writer/hlsl/generator_impl.h b/src/writer/hlsl/generator_impl.h
index 834fd7c..9ac8e10 100644
--- a/src/writer/hlsl/generator_impl.h
+++ b/src/writer/hlsl/generator_impl.h
@@ -34,12 +34,12 @@
 #include "src/ast/literal.h"
 #include "src/ast/loop_statement.h"
 #include "src/ast/member_accessor_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/return_statement.h"
 #include "src/ast/scalar_constructor_expression.h"
 #include "src/ast/switch_statement.h"
 #include "src/ast/type_constructor_expression.h"
 #include "src/ast/unary_op_expression.h"
+#include "src/program.h"
 #include "src/scope_stack.h"
 #include "src/type/struct_type.h"
 #include "src/writer/hlsl/namer.h"
@@ -52,8 +52,8 @@
 class GeneratorImpl {
  public:
   /// Constructor
-  /// @param module the module to generate
-  explicit GeneratorImpl(ast::Module* module);
+  /// @param program the program to generate
+  explicit GeneratorImpl(const Program* program);
   ~GeneratorImpl();
 
   /// Increment the emitter indent level
@@ -393,7 +393,7 @@
   size_t indent_ = 0;
 
   Namer namer_;
-  ast::Module* module_ = nullptr;
+  const Program* program_ = nullptr;
   Symbol current_ep_sym_;
   bool generating_entry_point_ = false;
   uint32_t loop_emission_counter_ = 0;
diff --git a/src/writer/hlsl/generator_impl_array_accessor_test.cc b/src/writer/hlsl/generator_impl_array_accessor_test.cc
index 79cf085..503186a 100644
--- a/src/writer/hlsl/generator_impl_array_accessor_test.cc
+++ b/src/writer/hlsl/generator_impl_array_accessor_test.cc
@@ -16,9 +16,9 @@
 
 #include "src/ast/array_accessor_expression.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/scalar_constructor_expression.h"
 #include "src/ast/sint_literal.h"
+#include "src/program.h"
 #include "src/type/i32_type.h"
 #include "src/writer/hlsl/test_helper.h"
 
diff --git a/src/writer/hlsl/generator_impl_assign_test.cc b/src/writer/hlsl/generator_impl_assign_test.cc
index c44681c..be2f2dd 100644
--- a/src/writer/hlsl/generator_impl_assign_test.cc
+++ b/src/writer/hlsl/generator_impl_assign_test.cc
@@ -17,7 +17,7 @@
 
 #include "src/ast/assignment_statement.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/writer/hlsl/test_helper.h"
 
 namespace tint {
diff --git a/src/writer/hlsl/generator_impl_binary_test.cc b/src/writer/hlsl/generator_impl_binary_test.cc
index 704cb5a..c0a0e03 100644
--- a/src/writer/hlsl/generator_impl_binary_test.cc
+++ b/src/writer/hlsl/generator_impl_binary_test.cc
@@ -24,13 +24,13 @@
 #include "src/ast/function.h"
 #include "src/ast/identifier_expression.h"
 #include "src/ast/if_statement.h"
-#include "src/ast/module.h"
 #include "src/ast/return_statement.h"
 #include "src/ast/scalar_constructor_expression.h"
 #include "src/ast/sint_literal.h"
 #include "src/ast/type_constructor_expression.h"
 #include "src/ast/variable.h"
 #include "src/ast/variable_decl_statement.h"
+#include "src/program.h"
 #include "src/type/bool_type.h"
 #include "src/type/f32_type.h"
 #include "src/type/i32_type.h"
diff --git a/src/writer/hlsl/generator_impl_bitcast_test.cc b/src/writer/hlsl/generator_impl_bitcast_test.cc
index f4c9f39..eecefe0 100644
--- a/src/writer/hlsl/generator_impl_bitcast_test.cc
+++ b/src/writer/hlsl/generator_impl_bitcast_test.cc
@@ -16,7 +16,7 @@
 
 #include "src/ast/bitcast_expression.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/type/f32_type.h"
 #include "src/type/i32_type.h"
 #include "src/type/u32_type.h"
diff --git a/src/writer/hlsl/generator_impl_break_test.cc b/src/writer/hlsl/generator_impl_break_test.cc
index e7b865c..36715bf 100644
--- a/src/writer/hlsl/generator_impl_break_test.cc
+++ b/src/writer/hlsl/generator_impl_break_test.cc
@@ -16,7 +16,7 @@
 #include <vector>
 
 #include "src/ast/break_statement.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/writer/hlsl/test_helper.h"
 
 namespace tint {
diff --git a/src/writer/hlsl/generator_impl_call_test.cc b/src/writer/hlsl/generator_impl_call_test.cc
index 5b3a25c..c03e631 100644
--- a/src/writer/hlsl/generator_impl_call_test.cc
+++ b/src/writer/hlsl/generator_impl_call_test.cc
@@ -18,7 +18,7 @@
 #include "src/ast/call_statement.h"
 #include "src/ast/function.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/type/void_type.h"
 #include "src/writer/hlsl/test_helper.h"
 
diff --git a/src/writer/hlsl/generator_impl_case_test.cc b/src/writer/hlsl/generator_impl_case_test.cc
index b60e7e5..827ee1b 100644
--- a/src/writer/hlsl/generator_impl_case_test.cc
+++ b/src/writer/hlsl/generator_impl_case_test.cc
@@ -18,8 +18,8 @@
 #include "src/ast/case_statement.h"
 #include "src/ast/fallthrough_statement.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/sint_literal.h"
+#include "src/program.h"
 #include "src/type/i32_type.h"
 #include "src/writer/hlsl/test_helper.h"
 
diff --git a/src/writer/hlsl/generator_impl_cast_test.cc b/src/writer/hlsl/generator_impl_cast_test.cc
index de0d39f..a6ef210 100644
--- a/src/writer/hlsl/generator_impl_cast_test.cc
+++ b/src/writer/hlsl/generator_impl_cast_test.cc
@@ -15,8 +15,8 @@
 #include <memory>
 
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/type_constructor_expression.h"
+#include "src/program.h"
 #include "src/type/f32_type.h"
 #include "src/type/vector_type.h"
 #include "src/writer/hlsl/test_helper.h"
diff --git a/src/writer/hlsl/generator_impl_constructor_test.cc b/src/writer/hlsl/generator_impl_constructor_test.cc
index 071d240..1a284c6 100644
--- a/src/writer/hlsl/generator_impl_constructor_test.cc
+++ b/src/writer/hlsl/generator_impl_constructor_test.cc
@@ -14,11 +14,11 @@
 
 #include "src/ast/bool_literal.h"
 #include "src/ast/float_literal.h"
-#include "src/ast/module.h"
 #include "src/ast/scalar_constructor_expression.h"
 #include "src/ast/sint_literal.h"
 #include "src/ast/type_constructor_expression.h"
 #include "src/ast/uint_literal.h"
+#include "src/program.h"
 #include "src/type/array_type.h"
 #include "src/type/bool_type.h"
 #include "src/type/f32_type.h"
diff --git a/src/writer/hlsl/generator_impl_continue_test.cc b/src/writer/hlsl/generator_impl_continue_test.cc
index f87de21..f934078 100644
--- a/src/writer/hlsl/generator_impl_continue_test.cc
+++ b/src/writer/hlsl/generator_impl_continue_test.cc
@@ -16,7 +16,7 @@
 #include <vector>
 
 #include "src/ast/continue_statement.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/writer/hlsl/test_helper.h"
 
 namespace tint {
diff --git a/src/writer/hlsl/generator_impl_discard_test.cc b/src/writer/hlsl/generator_impl_discard_test.cc
index 9d0c425..574c397 100644
--- a/src/writer/hlsl/generator_impl_discard_test.cc
+++ b/src/writer/hlsl/generator_impl_discard_test.cc
@@ -13,7 +13,7 @@
 // limitations under the License.
 
 #include "src/ast/discard_statement.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/writer/hlsl/test_helper.h"
 
 namespace tint {
diff --git a/src/writer/hlsl/generator_impl_function_entry_point_data_test.cc b/src/writer/hlsl/generator_impl_function_entry_point_data_test.cc
index e29725fe..5743f6a 100644
--- a/src/writer/hlsl/generator_impl_function_entry_point_data_test.cc
+++ b/src/writer/hlsl/generator_impl_function_entry_point_data_test.cc
@@ -19,11 +19,11 @@
 #include "src/ast/identifier_expression.h"
 #include "src/ast/location_decoration.h"
 #include "src/ast/member_accessor_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/pipeline_stage.h"
 #include "src/ast/return_statement.h"
 #include "src/ast/stage_decoration.h"
 #include "src/ast/variable.h"
+#include "src/program.h"
 #include "src/type_determiner.h"
 #include "src/writer/hlsl/test_helper.h"
 
diff --git a/src/writer/hlsl/generator_impl_function_test.cc b/src/writer/hlsl/generator_impl_function_test.cc
index d799d0f..a6350b4 100644
--- a/src/writer/hlsl/generator_impl_function_test.cc
+++ b/src/writer/hlsl/generator_impl_function_test.cc
@@ -23,7 +23,6 @@
 #include "src/ast/if_statement.h"
 #include "src/ast/location_decoration.h"
 #include "src/ast/member_accessor_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/pipeline_stage.h"
 #include "src/ast/return_statement.h"
 #include "src/ast/scalar_constructor_expression.h"
@@ -35,6 +34,7 @@
 #include "src/ast/variable.h"
 #include "src/ast/variable_decl_statement.h"
 #include "src/ast/workgroup_decoration.h"
+#include "src/program.h"
 #include "src/type/access_control_type.h"
 #include "src/type/array_type.h"
 #include "src/type/f32_type.h"
diff --git a/src/writer/hlsl/generator_impl_identifier_test.cc b/src/writer/hlsl/generator_impl_identifier_test.cc
index eaaebc1..0c311cc 100644
--- a/src/writer/hlsl/generator_impl_identifier_test.cc
+++ b/src/writer/hlsl/generator_impl_identifier_test.cc
@@ -13,7 +13,7 @@
 // limitations under the License.
 
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/writer/hlsl/test_helper.h"
 
 namespace tint {
diff --git a/src/writer/hlsl/generator_impl_if_test.cc b/src/writer/hlsl/generator_impl_if_test.cc
index 1e67070..314a103 100644
--- a/src/writer/hlsl/generator_impl_if_test.cc
+++ b/src/writer/hlsl/generator_impl_if_test.cc
@@ -15,8 +15,8 @@
 #include "src/ast/else_statement.h"
 #include "src/ast/identifier_expression.h"
 #include "src/ast/if_statement.h"
-#include "src/ast/module.h"
 #include "src/ast/return_statement.h"
+#include "src/program.h"
 #include "src/writer/hlsl/test_helper.h"
 
 namespace tint {
diff --git a/src/writer/hlsl/generator_impl_import_test.cc b/src/writer/hlsl/generator_impl_import_test.cc
index 8613a0d..7b1f2b4 100644
--- a/src/writer/hlsl/generator_impl_import_test.cc
+++ b/src/writer/hlsl/generator_impl_import_test.cc
@@ -19,10 +19,10 @@
 #include "src/ast/call_expression.h"
 #include "src/ast/float_literal.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/scalar_constructor_expression.h"
 #include "src/ast/sint_literal.h"
 #include "src/ast/type_constructor_expression.h"
+#include "src/program.h"
 #include "src/type/f32_type.h"
 #include "src/type/i32_type.h"
 #include "src/type/matrix_type.h"
diff --git a/src/writer/hlsl/generator_impl_intrinsic_test.cc b/src/writer/hlsl/generator_impl_intrinsic_test.cc
index a3b0a71..6f73c2c 100644
--- a/src/writer/hlsl/generator_impl_intrinsic_test.cc
+++ b/src/writer/hlsl/generator_impl_intrinsic_test.cc
@@ -14,7 +14,7 @@
 
 #include "src/ast/call_expression.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/type/f32_type.h"
 #include "src/type/vector_type.h"
 #include "src/type_determiner.h"
diff --git a/src/writer/hlsl/generator_impl_loop_test.cc b/src/writer/hlsl/generator_impl_loop_test.cc
index 09befb2..03d4e84 100644
--- a/src/writer/hlsl/generator_impl_loop_test.cc
+++ b/src/writer/hlsl/generator_impl_loop_test.cc
@@ -19,10 +19,10 @@
 #include "src/ast/float_literal.h"
 #include "src/ast/identifier_expression.h"
 #include "src/ast/loop_statement.h"
-#include "src/ast/module.h"
 #include "src/ast/return_statement.h"
 #include "src/ast/variable.h"
 #include "src/ast/variable_decl_statement.h"
+#include "src/program.h"
 #include "src/type/f32_type.h"
 #include "src/writer/hlsl/test_helper.h"
 
diff --git a/src/writer/hlsl/generator_impl_member_accessor_test.cc b/src/writer/hlsl/generator_impl_member_accessor_test.cc
index e1ade73..06be7a3 100644
--- a/src/writer/hlsl/generator_impl_member_accessor_test.cc
+++ b/src/writer/hlsl/generator_impl_member_accessor_test.cc
@@ -18,7 +18,6 @@
 #include "src/ast/assignment_statement.h"
 #include "src/ast/identifier_expression.h"
 #include "src/ast/member_accessor_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/scalar_constructor_expression.h"
 #include "src/ast/sint_literal.h"
 #include "src/ast/stride_decoration.h"
@@ -27,6 +26,7 @@
 #include "src/ast/struct_member_offset_decoration.h"
 #include "src/ast/type_constructor_expression.h"
 #include "src/ast/variable.h"
+#include "src/program.h"
 #include "src/type/struct_type.h"
 #include "src/type/vector_type.h"
 #include "src/type_determiner.h"
diff --git a/src/writer/hlsl/generator_impl_module_constant_test.cc b/src/writer/hlsl/generator_impl_module_constant_test.cc
index 057162f..1932b0a 100644
--- a/src/writer/hlsl/generator_impl_module_constant_test.cc
+++ b/src/writer/hlsl/generator_impl_module_constant_test.cc
@@ -17,10 +17,10 @@
 
 #include "src/ast/constant_id_decoration.h"
 #include "src/ast/float_literal.h"
-#include "src/ast/module.h"
 #include "src/ast/scalar_constructor_expression.h"
 #include "src/ast/type_constructor_expression.h"
 #include "src/ast/variable.h"
+#include "src/program.h"
 #include "src/type/array_type.h"
 #include "src/type/f32_type.h"
 #include "src/writer/hlsl/test_helper.h"
diff --git a/src/writer/hlsl/generator_impl_return_test.cc b/src/writer/hlsl/generator_impl_return_test.cc
index 4c04d90..7545928 100644
--- a/src/writer/hlsl/generator_impl_return_test.cc
+++ b/src/writer/hlsl/generator_impl_return_test.cc
@@ -16,8 +16,8 @@
 #include <vector>
 
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/return_statement.h"
+#include "src/program.h"
 #include "src/writer/hlsl/test_helper.h"
 
 namespace tint {
diff --git a/src/writer/hlsl/generator_impl_switch_test.cc b/src/writer/hlsl/generator_impl_switch_test.cc
index 75039eb..8106f85 100644
--- a/src/writer/hlsl/generator_impl_switch_test.cc
+++ b/src/writer/hlsl/generator_impl_switch_test.cc
@@ -17,9 +17,9 @@
 #include "src/ast/break_statement.h"
 #include "src/ast/case_statement.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/sint_literal.h"
 #include "src/ast/switch_statement.h"
+#include "src/program.h"
 #include "src/type/i32_type.h"
 #include "src/writer/hlsl/test_helper.h"
 
diff --git a/src/writer/hlsl/generator_impl_test.cc b/src/writer/hlsl/generator_impl_test.cc
index a42c4b9..d3e36ab 100644
--- a/src/writer/hlsl/generator_impl_test.cc
+++ b/src/writer/hlsl/generator_impl_test.cc
@@ -16,7 +16,7 @@
 
 #include "src/ast/function.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/type/void_type.h"
 #include "src/writer/hlsl/test_helper.h"
 
diff --git a/src/writer/hlsl/generator_impl_type_test.cc b/src/writer/hlsl/generator_impl_type_test.cc
index 2d69d2b..c4bf8ed 100644
--- a/src/writer/hlsl/generator_impl_type_test.cc
+++ b/src/writer/hlsl/generator_impl_type_test.cc
@@ -12,13 +12,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "src/ast/module.h"
 #include "src/ast/struct.h"
 #include "src/ast/struct_block_decoration.h"
 #include "src/ast/struct_decoration.h"
 #include "src/ast/struct_member.h"
 #include "src/ast/struct_member_decoration.h"
 #include "src/ast/struct_member_offset_decoration.h"
+#include "src/program.h"
 #include "src/type/access_control_type.h"
 #include "src/type/array_type.h"
 #include "src/type/bool_type.h"
diff --git a/src/writer/hlsl/generator_impl_unary_op_test.cc b/src/writer/hlsl/generator_impl_unary_op_test.cc
index 48294c1..86704d2 100644
--- a/src/writer/hlsl/generator_impl_unary_op_test.cc
+++ b/src/writer/hlsl/generator_impl_unary_op_test.cc
@@ -16,8 +16,8 @@
 #include <vector>
 
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/unary_op_expression.h"
+#include "src/program.h"
 #include "src/writer/hlsl/test_helper.h"
 
 namespace tint {
diff --git a/src/writer/hlsl/generator_impl_variable_decl_statement_test.cc b/src/writer/hlsl/generator_impl_variable_decl_statement_test.cc
index 91ca67e..eaa1232 100644
--- a/src/writer/hlsl/generator_impl_variable_decl_statement_test.cc
+++ b/src/writer/hlsl/generator_impl_variable_decl_statement_test.cc
@@ -16,9 +16,9 @@
 #include <vector>
 
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/variable.h"
 #include "src/ast/variable_decl_statement.h"
+#include "src/program.h"
 #include "src/type/array_type.h"
 #include "src/type/f32_type.h"
 #include "src/type/matrix_type.h"
diff --git a/src/writer/hlsl/test_helper.h b/src/writer/hlsl/test_helper.h
index af3d10a..530b261 100644
--- a/src/writer/hlsl/test_helper.h
+++ b/src/writer/hlsl/test_helper.h
@@ -31,12 +31,12 @@
 
 /// Helper class for testing
 template <typename BODY>
-class TestHelperBase : public BODY, public ast::BuilderWithModule {
+class TestHelperBase : public BODY, public ast::BuilderWithProgram {
  public:
-  TestHelperBase() : td(mod) {}
+  TestHelperBase() : td(program) {}
   ~TestHelperBase() = default;
 
-  /// Builds and returns a GeneratorImpl from the module.
+  /// Builds and returns a GeneratorImpl from the program.
   /// @note The generator is only built once. Multiple calls to Build() will
   /// return the same GeneratorImpl without rebuilding.
   /// @return the built generator
@@ -44,7 +44,7 @@
     if (gen_) {
       return *gen_;
     }
-    gen_ = std::make_unique<GeneratorImpl>(mod);
+    gen_ = std::make_unique<GeneratorImpl>(program);
     return *gen_;
   }
 
diff --git a/src/writer/msl/generator.cc b/src/writer/msl/generator.cc
index 5c6428c..66b609b 100644
--- a/src/writer/msl/generator.cc
+++ b/src/writer/msl/generator.cc
@@ -20,12 +20,8 @@
 namespace writer {
 namespace msl {
 
-Generator::Generator(ast::Module module)
-    : module_(std::move(module)),
-      impl_(std::make_unique<GeneratorImpl>(&module_)) {}
-
-Generator::Generator(Program* program)
-    : impl_(std::make_unique<GeneratorImpl>(&program->module)) {}
+Generator::Generator(const Program* program)
+    : impl_(std::make_unique<GeneratorImpl>(program)) {}
 
 Generator::~Generator() = default;
 
diff --git a/src/writer/msl/generator.h b/src/writer/msl/generator.h
index 7586a5a..a677958 100644
--- a/src/writer/msl/generator.h
+++ b/src/writer/msl/generator.h
@@ -30,12 +30,8 @@
 class Generator : public Text {
  public:
   /// Constructor
-  /// @param module the module to convert
-  explicit Generator(ast::Module module);
-
-  /// Constructor
   /// @param program the program to convert
-  explicit Generator(Program* program);
+  explicit Generator(const Program* program);
 
   /// Destructor
   ~Generator() override;
@@ -58,7 +54,6 @@
   std::string error() const;
 
  private:
-  ast::Module module_;
   std::unique_ptr<GeneratorImpl> impl_;
 };
 
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc
index b0be9aa..b88dd5a 100644
--- a/src/writer/msl/generator_impl.cc
+++ b/src/writer/msl/generator_impl.cc
@@ -96,8 +96,8 @@
 
 }  // namespace
 
-GeneratorImpl::GeneratorImpl(ast::Module* module)
-    : TextGenerator(), module_(module) {}
+GeneratorImpl::GeneratorImpl(const Program* program)
+    : TextGenerator(), program_(program) {}
 
 GeneratorImpl::~GeneratorImpl() = default;
 
@@ -115,20 +115,20 @@
 bool GeneratorImpl::Generate() {
   out_ << "#include <metal_stdlib>" << std::endl << std::endl;
 
-  for (auto* global : module_->global_variables()) {
+  for (auto* global : program_->global_variables()) {
     global_variables_.set(global->symbol(), global);
   }
 
-  for (auto* const ty : module_->constructed_types()) {
+  for (auto* const ty : program_->constructed_types()) {
     if (!EmitConstructedType(ty)) {
       return false;
     }
   }
-  if (!module_->constructed_types().empty()) {
+  if (!program_->constructed_types().empty()) {
     out_ << std::endl;
   }
 
-  for (auto* var : module_->global_variables()) {
+  for (auto* var : program_->global_variables()) {
     if (!var->is_const()) {
       continue;
     }
@@ -138,7 +138,7 @@
   }
 
   // Make sure all entry point data is emitted before the entry point functions
-  for (auto* func : module_->Functions()) {
+  for (auto* func : program_->Functions()) {
     if (!func->IsEntryPoint()) {
       continue;
     }
@@ -148,13 +148,13 @@
     }
   }
 
-  for (auto* func : module_->Functions()) {
+  for (auto* func : program_->Functions()) {
     if (!EmitFunction(func)) {
       return false;
     }
   }
 
-  for (auto* func : module_->Functions()) {
+  for (auto* func : program_->Functions()) {
     if (!func->IsEntryPoint()) {
       continue;
     }
@@ -258,8 +258,8 @@
     if (!EmitType(alias->type(), "")) {
       return false;
     }
-    out_ << " " << namer_.NameFor(module_->SymbolToName(alias->symbol())) << ";"
-         << std::endl;
+    out_ << " " << namer_.NameFor(program_->SymbolToName(alias->symbol()))
+         << ";" << std::endl;
   } else if (auto* str = ty->As<type::Struct>()) {
     if (!EmitStructType(str)) {
       return false;
@@ -517,7 +517,7 @@
     return true;
   }
 
-  auto name = module_->SymbolToName(ident->symbol());
+  auto name = program_->SymbolToName(ident->symbol());
   auto caller_sym = ident->symbol();
   auto it = ep_func_name_remapped_.find(current_ep_sym_.to_str() + "_" +
                                         caller_sym.to_str());
@@ -525,10 +525,10 @@
     name = it->second;
   }
 
-  auto* func = module_->Functions().Find(ident->symbol());
+  auto* func = program_->Functions().Find(ident->symbol());
   if (func == nullptr) {
     error_ =
-        "Unable to find function: " + module_->SymbolToName(ident->symbol());
+        "Unable to find function: " + program_->SymbolToName(ident->symbol());
     return false;
   }
 
@@ -562,7 +562,7 @@
       out_ << ", ";
     }
     first = false;
-    out_ << module_->SymbolToName(var->symbol());
+    out_ << program_->SymbolToName(var->symbol());
   }
 
   for (const auto& data : func->referenced_uniform_variables()) {
@@ -571,7 +571,7 @@
       out_ << ", ";
     }
     first = false;
-    out_ << module_->SymbolToName(var->symbol());
+    out_ << program_->SymbolToName(var->symbol());
   }
 
   for (const auto& data : func->referenced_storagebuffer_variables()) {
@@ -580,7 +580,7 @@
       out_ << ", ";
     }
     first = false;
-    out_ << module_->SymbolToName(var->symbol());
+    out_ << program_->SymbolToName(var->symbol());
   }
 
   const auto& params = expr->params();
@@ -720,7 +720,7 @@
       break;
     default:
       error_ = "Internal compiler error: Unhandled texture intrinsic '" +
-               module_->SymbolToName(ident->symbol()) + "'";
+               program_->SymbolToName(ident->symbol()) + "'";
       return false;
   }
 
@@ -847,7 +847,7 @@
     case ast::Intrinsic::kTrunc:
     case ast::Intrinsic::kSign:
     case ast::Intrinsic::kClamp:
-      out += module_->SymbolToName(ident->symbol());
+      out += program_->SymbolToName(ident->symbol());
       break;
     case ast::Intrinsic::kAbs:
       if (ident->result_type()->Is<type::F32>()) {
@@ -884,7 +884,7 @@
       break;
     default:
       error_ =
-          "Unknown import method: " + module_->SymbolToName(ident->symbol());
+          "Unknown import method: " + program_->SymbolToName(ident->symbol());
       return "";
   }
   return out;
@@ -1059,7 +1059,7 @@
   }
 
   if (!in_locations.empty()) {
-    auto in_struct_name = generate_name(module_->SymbolToName(func->symbol()) +
+    auto in_struct_name = generate_name(program_->SymbolToName(func->symbol()) +
                                         "_" + kInStructNameSuffix);
     auto in_var_name = generate_name(kTintStructInVarPrefix);
     ep_sym_to_in_data_[func->symbol()] = {in_struct_name, in_var_name};
@@ -1074,11 +1074,11 @@
       uint32_t loc = data.second;
 
       make_indent();
-      if (!EmitType(var->type(), module_->SymbolToName(var->symbol()))) {
+      if (!EmitType(var->type(), program_->SymbolToName(var->symbol()))) {
         return false;
       }
 
-      out_ << " " << module_->SymbolToName(var->symbol()) << " [[";
+      out_ << " " << program_->SymbolToName(var->symbol()) << " [[";
       if (func->pipeline_stage() == ast::PipelineStage::kVertex) {
         out_ << "attribute(" << loc << ")";
       } else if (func->pipeline_stage() == ast::PipelineStage::kFragment) {
@@ -1096,8 +1096,8 @@
   }
 
   if (!out_variables.empty()) {
-    auto out_struct_name = generate_name(module_->SymbolToName(func->symbol()) +
-                                         "_" + kOutStructNameSuffix);
+    auto out_struct_name = generate_name(
+        program_->SymbolToName(func->symbol()) + "_" + kOutStructNameSuffix);
     auto out_var_name = generate_name(kTintStructOutVarPrefix);
     ep_sym_to_out_data_[func->symbol()] = {out_struct_name, out_var_name};
 
@@ -1110,11 +1110,11 @@
       auto* deco = data.second;
 
       make_indent();
-      if (!EmitType(var->type(), module_->SymbolToName(var->symbol()))) {
+      if (!EmitType(var->type(), program_->SymbolToName(var->symbol()))) {
         return false;
       }
 
-      out_ << " " << module_->SymbolToName(var->symbol()) << " [[";
+      out_ << " " << program_->SymbolToName(var->symbol()) << " [[";
 
       if (auto* location = deco->As<ast::LocationDecoration>()) {
         auto loc = location->value();
@@ -1272,12 +1272,12 @@
     auto ep_name = ep_sym.to_str();
     // TODO(dsinclair): The SymbolToName should go away and just use
     // to_str() here when the conversion is complete.
-    name = generate_name(module_->SymbolToName(func->symbol()) + "_" +
-                         module_->SymbolToName(ep_sym));
+    name = generate_name(program_->SymbolToName(func->symbol()) + "_" +
+                         program_->SymbolToName(ep_sym));
     ep_func_name_remapped_[ep_name + "_" + func_name] = name;
   } else {
     // TODO(dsinclair): this should be updated to a remapped name
-    name = namer_.NameFor(module_->SymbolToName(func->symbol()));
+    name = namer_.NameFor(program_->SymbolToName(func->symbol()));
   }
   out_ << name << "(";
 
@@ -1320,7 +1320,7 @@
     if (!EmitType(var->type(), "")) {
       return false;
     }
-    out_ << "& " << module_->SymbolToName(var->symbol());
+    out_ << "& " << program_->SymbolToName(var->symbol());
   }
 
   for (const auto& data : func->referenced_uniform_variables()) {
@@ -1335,7 +1335,7 @@
     if (!EmitType(var->type(), "")) {
       return false;
     }
-    out_ << "& " << module_->SymbolToName(var->symbol());
+    out_ << "& " << program_->SymbolToName(var->symbol());
   }
 
   for (const auto& data : func->referenced_storagebuffer_variables()) {
@@ -1358,7 +1358,7 @@
     if (!EmitType(ac->type(), "")) {
       return false;
     }
-    out_ << "& " << module_->SymbolToName(var->symbol());
+    out_ << "& " << program_->SymbolToName(var->symbol());
   }
 
   for (auto* v : func->params()) {
@@ -1367,12 +1367,12 @@
     }
     first = false;
 
-    if (!EmitType(v->type(), module_->SymbolToName(v->symbol()))) {
+    if (!EmitType(v->type(), program_->SymbolToName(v->symbol()))) {
       return false;
     }
     // Array name is output as part of the type
     if (!v->type()->Is<type::Array>()) {
-      out_ << " " << module_->SymbolToName(v->symbol());
+      out_ << " " << program_->SymbolToName(v->symbol());
     }
   }
 
@@ -1432,7 +1432,7 @@
   } else {
     out_ << "void";
   }
-  out_ << " " << namer_.NameFor(module_->SymbolToName(func->symbol())) << "(";
+  out_ << " " << namer_.NameFor(program_->SymbolToName(func->symbol())) << "(";
 
   bool first = true;
   auto in_data = ep_sym_to_in_data_.find(current_ep_sym_);
@@ -1464,7 +1464,7 @@
       error_ = "unknown builtin";
       return false;
     }
-    out_ << " " << module_->SymbolToName(var->symbol()) << " [[" << attr
+    out_ << " " << program_->SymbolToName(var->symbol()) << " [[" << attr
          << "]]";
   }
 
@@ -1481,7 +1481,7 @@
     auto* binding = data.second.binding;
     if (binding == nullptr) {
       error_ = "unable to find binding information for uniform: " +
-               module_->SymbolToName(var->symbol());
+               program_->SymbolToName(var->symbol());
       return false;
     }
     // auto* set = data.second.set;
@@ -1492,7 +1492,7 @@
     if (!EmitType(var->type(), "")) {
       return false;
     }
-    out_ << "& " << module_->SymbolToName(var->symbol()) << " [[buffer("
+    out_ << "& " << program_->SymbolToName(var->symbol()) << " [[buffer("
          << binding->value() << ")]]";
   }
 
@@ -1522,7 +1522,7 @@
     if (!EmitType(ac->type(), "")) {
       return false;
     }
-    out_ << "& " << module_->SymbolToName(var->symbol()) << " [[buffer("
+    out_ << "& " << program_->SymbolToName(var->symbol()) << " [[buffer("
          << binding->value() << ")]]";
   }
 
@@ -1587,7 +1587,7 @@
       out_ << name << ".";
     }
   }
-  out_ << namer_.NameFor(module_->SymbolToName(ident->symbol()));
+  out_ << namer_.NameFor(program_->SymbolToName(ident->symbol()));
 
   return true;
 }
@@ -1646,7 +1646,7 @@
       make_indent();
 
       auto* var = decl->variable();
-      out_ << module_->SymbolToName(var->symbol()) << " = ";
+      out_ << program_->SymbolToName(var->symbol()) << " = ";
       if (var->constructor() != nullptr) {
         if (!EmitExpression(var->constructor())) {
           return false;
@@ -1877,7 +1877,7 @@
   }
 
   if (auto* alias = type->As<type::Alias>()) {
-    out_ << namer_.NameFor(module_->SymbolToName(alias->symbol()));
+    out_ << namer_.NameFor(program_->SymbolToName(alias->symbol()));
   } else if (auto* ary = type->As<type::Array>()) {
     type::Type* base_type = ary;
     std::vector<uint32_t> sizes;
@@ -1920,7 +1920,7 @@
   } else if (auto* str = type->As<type::Struct>()) {
     // The struct type emits as just the name. The declaration would be emitted
     // as part of emitting the constructed types.
-    out_ << module_->SymbolToName(str->symbol());
+    out_ << program_->SymbolToName(str->symbol());
   } else if (auto* tex = type->As<type::Texture>()) {
     if (tex->Is<type::DepthTexture>()) {
       out_ << "depth";
@@ -2002,7 +2002,7 @@
   // TODO(dsinclair): Block decoration?
   // if (str->impl()->decoration() != ast::StructDecoration::kNone) {
   // }
-  out_ << "struct " << module_->SymbolToName(str->symbol()) << " {"
+  out_ << "struct " << program_->SymbolToName(str->symbol()) << " {"
        << std::endl;
 
   increment_indent();
@@ -2026,7 +2026,7 @@
       }
     }
 
-    if (!EmitType(mem->type(), module_->SymbolToName(mem->symbol()))) {
+    if (!EmitType(mem->type(), program_->SymbolToName(mem->symbol()))) {
       return false;
     }
     auto size = calculate_alignment_size(mem->type());
@@ -2038,7 +2038,7 @@
 
     // Array member name will be output with the type
     if (!mem->type()->Is<type::Array>()) {
-      out_ << " " << namer_.NameFor(module_->SymbolToName(mem->symbol()));
+      out_ << " " << namer_.NameFor(program_->SymbolToName(mem->symbol()));
     }
     out_ << ";" << std::endl;
   }
@@ -2080,11 +2080,11 @@
   if (var->is_const()) {
     out_ << "const ";
   }
-  if (!EmitType(var->type(), module_->SymbolToName(var->symbol()))) {
+  if (!EmitType(var->type(), program_->SymbolToName(var->symbol()))) {
     return false;
   }
   if (!var->type()->Is<type::Array>()) {
-    out_ << " " << module_->SymbolToName(var->symbol());
+    out_ << " " << program_->SymbolToName(var->symbol());
   }
 
   if (!skip_constructor) {
@@ -2122,11 +2122,11 @@
   }
 
   out_ << "constant ";
-  if (!EmitType(var->type(), module_->SymbolToName(var->symbol()))) {
+  if (!EmitType(var->type(), program_->SymbolToName(var->symbol()))) {
     return false;
   }
   if (!var->type()->Is<type::Array>()) {
-    out_ << " " << module_->SymbolToName(var->symbol());
+    out_ << " " << program_->SymbolToName(var->symbol());
   }
 
   if (var->HasConstantIdDecoration()) {
diff --git a/src/writer/msl/generator_impl.h b/src/writer/msl/generator_impl.h
index 95b6109..d3b56d2 100644
--- a/src/writer/msl/generator_impl.h
+++ b/src/writer/msl/generator_impl.h
@@ -35,12 +35,12 @@
 #include "src/ast/literal.h"
 #include "src/ast/loop_statement.h"
 #include "src/ast/member_accessor_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/return_statement.h"
 #include "src/ast/scalar_constructor_expression.h"
 #include "src/ast/switch_statement.h"
 #include "src/ast/type_constructor_expression.h"
 #include "src/ast/unary_op_expression.h"
+#include "src/program.h"
 #include "src/scope_stack.h"
 #include "src/type/struct_type.h"
 #include "src/writer/msl/namer.h"
@@ -54,8 +54,8 @@
 class GeneratorImpl : public TextGenerator {
  public:
   /// Constructor
-  /// @param module the module to generate
-  explicit GeneratorImpl(ast::Module* module);
+  /// @param program the program to generate
+  explicit GeneratorImpl(const Program* program);
   ~GeneratorImpl();
 
   /// @returns true on successful generation; false otherwise
@@ -284,7 +284,7 @@
   ScopeStack<ast::Variable*> global_variables_;
   Symbol current_ep_sym_;
   bool generating_entry_point_ = false;
-  const ast::Module* module_ = nullptr;
+  const Program* program_ = nullptr;
   uint32_t loop_emission_counter_ = 0;
 
   std::unordered_map<Symbol, EntryPointData> ep_sym_to_in_data_;
diff --git a/src/writer/msl/generator_impl_alias_type_test.cc b/src/writer/msl/generator_impl_alias_type_test.cc
index 055d804..bd98cc2 100644
--- a/src/writer/msl/generator_impl_alias_type_test.cc
+++ b/src/writer/msl/generator_impl_alias_type_test.cc
@@ -13,9 +13,9 @@
 // limitations under the License.
 
 #include "gtest/gtest.h"
-#include "src/ast/module.h"
 #include "src/ast/struct.h"
 #include "src/ast/struct_member.h"
+#include "src/program.h"
 #include "src/type/struct_type.h"
 #include "src/writer/msl/generator_impl.h"
 #include "src/writer/msl/test_helper.h"
diff --git a/src/writer/msl/generator_impl_array_accessor_test.cc b/src/writer/msl/generator_impl_array_accessor_test.cc
index e8e6ce3..3ce8bb5 100644
--- a/src/writer/msl/generator_impl_array_accessor_test.cc
+++ b/src/writer/msl/generator_impl_array_accessor_test.cc
@@ -17,9 +17,9 @@
 #include "gtest/gtest.h"
 #include "src/ast/array_accessor_expression.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/scalar_constructor_expression.h"
 #include "src/ast/sint_literal.h"
+#include "src/program.h"
 #include "src/type/i32_type.h"
 #include "src/writer/msl/generator_impl.h"
 #include "src/writer/msl/test_helper.h"
diff --git a/src/writer/msl/generator_impl_assign_test.cc b/src/writer/msl/generator_impl_assign_test.cc
index 2266646..a730acd 100644
--- a/src/writer/msl/generator_impl_assign_test.cc
+++ b/src/writer/msl/generator_impl_assign_test.cc
@@ -18,7 +18,7 @@
 #include "gtest/gtest.h"
 #include "src/ast/assignment_statement.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/writer/msl/generator_impl.h"
 #include "src/writer/msl/test_helper.h"
 
diff --git a/src/writer/msl/generator_impl_binary_test.cc b/src/writer/msl/generator_impl_binary_test.cc
index 70b4498..75fb8ea 100644
--- a/src/writer/msl/generator_impl_binary_test.cc
+++ b/src/writer/msl/generator_impl_binary_test.cc
@@ -17,7 +17,7 @@
 #include "gtest/gtest.h"
 #include "src/ast/binary_expression.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/writer/msl/generator_impl.h"
 #include "src/writer/msl/test_helper.h"
 
diff --git a/src/writer/msl/generator_impl_bitcast_test.cc b/src/writer/msl/generator_impl_bitcast_test.cc
index fea3c59..9af5fdb 100644
--- a/src/writer/msl/generator_impl_bitcast_test.cc
+++ b/src/writer/msl/generator_impl_bitcast_test.cc
@@ -17,7 +17,7 @@
 #include "gtest/gtest.h"
 #include "src/ast/bitcast_expression.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/type/f32_type.h"
 #include "src/writer/msl/generator_impl.h"
 #include "src/writer/msl/test_helper.h"
diff --git a/src/writer/msl/generator_impl_break_test.cc b/src/writer/msl/generator_impl_break_test.cc
index 1c88fe2..e8047ca 100644
--- a/src/writer/msl/generator_impl_break_test.cc
+++ b/src/writer/msl/generator_impl_break_test.cc
@@ -17,7 +17,7 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/break_statement.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/writer/msl/generator_impl.h"
 #include "src/writer/msl/test_helper.h"
 
diff --git a/src/writer/msl/generator_impl_call_test.cc b/src/writer/msl/generator_impl_call_test.cc
index 679bfb0..f2164d6 100644
--- a/src/writer/msl/generator_impl_call_test.cc
+++ b/src/writer/msl/generator_impl_call_test.cc
@@ -19,7 +19,7 @@
 #include "src/ast/call_statement.h"
 #include "src/ast/function.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/type/void_type.h"
 #include "src/writer/msl/generator_impl.h"
 #include "src/writer/msl/test_helper.h"
diff --git a/src/writer/msl/generator_impl_case_test.cc b/src/writer/msl/generator_impl_case_test.cc
index bb550b9..e4cbeb5 100644
--- a/src/writer/msl/generator_impl_case_test.cc
+++ b/src/writer/msl/generator_impl_case_test.cc
@@ -19,8 +19,8 @@
 #include "src/ast/case_statement.h"
 #include "src/ast/fallthrough_statement.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/sint_literal.h"
+#include "src/program.h"
 #include "src/type/i32_type.h"
 #include "src/writer/msl/generator_impl.h"
 #include "src/writer/msl/test_helper.h"
diff --git a/src/writer/msl/generator_impl_cast_test.cc b/src/writer/msl/generator_impl_cast_test.cc
index 85b8d6a..f22ecbd 100644
--- a/src/writer/msl/generator_impl_cast_test.cc
+++ b/src/writer/msl/generator_impl_cast_test.cc
@@ -16,8 +16,8 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/type_constructor_expression.h"
+#include "src/program.h"
 #include "src/type/f32_type.h"
 #include "src/type/vector_type.h"
 #include "src/writer/msl/generator_impl.h"
diff --git a/src/writer/msl/generator_impl_constructor_test.cc b/src/writer/msl/generator_impl_constructor_test.cc
index 3da5647..3c9952c 100644
--- a/src/writer/msl/generator_impl_constructor_test.cc
+++ b/src/writer/msl/generator_impl_constructor_test.cc
@@ -15,11 +15,11 @@
 #include "gtest/gtest.h"
 #include "src/ast/bool_literal.h"
 #include "src/ast/float_literal.h"
-#include "src/ast/module.h"
 #include "src/ast/scalar_constructor_expression.h"
 #include "src/ast/sint_literal.h"
 #include "src/ast/type_constructor_expression.h"
 #include "src/ast/uint_literal.h"
+#include "src/program.h"
 #include "src/type/array_type.h"
 #include "src/type/bool_type.h"
 #include "src/type/f32_type.h"
diff --git a/src/writer/msl/generator_impl_continue_test.cc b/src/writer/msl/generator_impl_continue_test.cc
index 4ef8b55..45b42ef 100644
--- a/src/writer/msl/generator_impl_continue_test.cc
+++ b/src/writer/msl/generator_impl_continue_test.cc
@@ -17,7 +17,7 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/continue_statement.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/writer/msl/generator_impl.h"
 #include "src/writer/msl/test_helper.h"
 
diff --git a/src/writer/msl/generator_impl_discard_test.cc b/src/writer/msl/generator_impl_discard_test.cc
index c59bc5e..e624914 100644
--- a/src/writer/msl/generator_impl_discard_test.cc
+++ b/src/writer/msl/generator_impl_discard_test.cc
@@ -14,7 +14,7 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/discard_statement.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/writer/msl/generator_impl.h"
 #include "src/writer/msl/test_helper.h"
 
diff --git a/src/writer/msl/generator_impl_function_entry_point_data_test.cc b/src/writer/msl/generator_impl_function_entry_point_data_test.cc
index 00298f6..50dc20d 100644
--- a/src/writer/msl/generator_impl_function_entry_point_data_test.cc
+++ b/src/writer/msl/generator_impl_function_entry_point_data_test.cc
@@ -19,10 +19,10 @@
 #include "src/ast/identifier_expression.h"
 #include "src/ast/location_decoration.h"
 #include "src/ast/member_accessor_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/pipeline_stage.h"
 #include "src/ast/stage_decoration.h"
 #include "src/ast/variable.h"
+#include "src/program.h"
 #include "src/type/f32_type.h"
 #include "src/type/i32_type.h"
 #include "src/type/vector_type.h"
diff --git a/src/writer/msl/generator_impl_function_test.cc b/src/writer/msl/generator_impl_function_test.cc
index 0bec2fb..994839e 100644
--- a/src/writer/msl/generator_impl_function_test.cc
+++ b/src/writer/msl/generator_impl_function_test.cc
@@ -24,7 +24,6 @@
 #include "src/ast/if_statement.h"
 #include "src/ast/location_decoration.h"
 #include "src/ast/member_accessor_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/pipeline_stage.h"
 #include "src/ast/return_statement.h"
 #include "src/ast/scalar_constructor_expression.h"
@@ -37,6 +36,7 @@
 #include "src/ast/struct_member_offset_decoration.h"
 #include "src/ast/variable.h"
 #include "src/ast/variable_decl_statement.h"
+#include "src/program.h"
 #include "src/type/access_control_type.h"
 #include "src/type/array_type.h"
 #include "src/type/f32_type.h"
diff --git a/src/writer/msl/generator_impl_identifier_test.cc b/src/writer/msl/generator_impl_identifier_test.cc
index af19be1..6b4ebef 100644
--- a/src/writer/msl/generator_impl_identifier_test.cc
+++ b/src/writer/msl/generator_impl_identifier_test.cc
@@ -14,7 +14,7 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/writer/msl/generator_impl.h"
 #include "src/writer/msl/test_helper.h"
 
diff --git a/src/writer/msl/generator_impl_if_test.cc b/src/writer/msl/generator_impl_if_test.cc
index b1167a3d..ec8771c 100644
--- a/src/writer/msl/generator_impl_if_test.cc
+++ b/src/writer/msl/generator_impl_if_test.cc
@@ -16,8 +16,8 @@
 #include "src/ast/else_statement.h"
 #include "src/ast/identifier_expression.h"
 #include "src/ast/if_statement.h"
-#include "src/ast/module.h"
 #include "src/ast/return_statement.h"
+#include "src/program.h"
 #include "src/writer/msl/generator_impl.h"
 #include "src/writer/msl/test_helper.h"
 
diff --git a/src/writer/msl/generator_impl_import_test.cc b/src/writer/msl/generator_impl_import_test.cc
index 49688a3..110a6d1 100644
--- a/src/writer/msl/generator_impl_import_test.cc
+++ b/src/writer/msl/generator_impl_import_test.cc
@@ -20,10 +20,10 @@
 #include "src/ast/call_expression.h"
 #include "src/ast/float_literal.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/scalar_constructor_expression.h"
 #include "src/ast/sint_literal.h"
 #include "src/ast/type_constructor_expression.h"
+#include "src/program.h"
 #include "src/type/f32_type.h"
 #include "src/type/i32_type.h"
 #include "src/type/matrix_type.h"
diff --git a/src/writer/msl/generator_impl_intrinsic_test.cc b/src/writer/msl/generator_impl_intrinsic_test.cc
index 652d6ce..6ca651f 100644
--- a/src/writer/msl/generator_impl_intrinsic_test.cc
+++ b/src/writer/msl/generator_impl_intrinsic_test.cc
@@ -15,7 +15,7 @@
 #include "gtest/gtest.h"
 #include "src/ast/call_expression.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/type/f32_type.h"
 #include "src/type/vector_type.h"
 #include "src/type_determiner.h"
diff --git a/src/writer/msl/generator_impl_loop_test.cc b/src/writer/msl/generator_impl_loop_test.cc
index 7c42a84..1b7a756 100644
--- a/src/writer/msl/generator_impl_loop_test.cc
+++ b/src/writer/msl/generator_impl_loop_test.cc
@@ -20,10 +20,10 @@
 #include "src/ast/float_literal.h"
 #include "src/ast/identifier_expression.h"
 #include "src/ast/loop_statement.h"
-#include "src/ast/module.h"
 #include "src/ast/return_statement.h"
 #include "src/ast/variable.h"
 #include "src/ast/variable_decl_statement.h"
+#include "src/program.h"
 #include "src/type/f32_type.h"
 #include "src/writer/msl/generator_impl.h"
 #include "src/writer/msl/test_helper.h"
diff --git a/src/writer/msl/generator_impl_member_accessor_test.cc b/src/writer/msl/generator_impl_member_accessor_test.cc
index e1fdeaf..89ac2c6 100644
--- a/src/writer/msl/generator_impl_member_accessor_test.cc
+++ b/src/writer/msl/generator_impl_member_accessor_test.cc
@@ -17,7 +17,7 @@
 #include "gtest/gtest.h"
 #include "src/ast/identifier_expression.h"
 #include "src/ast/member_accessor_expression.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/writer/msl/generator_impl.h"
 #include "src/writer/msl/test_helper.h"
 
diff --git a/src/writer/msl/generator_impl_module_constant_test.cc b/src/writer/msl/generator_impl_module_constant_test.cc
index 1b7022a..8e4c7d5 100644
--- a/src/writer/msl/generator_impl_module_constant_test.cc
+++ b/src/writer/msl/generator_impl_module_constant_test.cc
@@ -18,10 +18,10 @@
 #include "gtest/gtest.h"
 #include "src/ast/constant_id_decoration.h"
 #include "src/ast/float_literal.h"
-#include "src/ast/module.h"
 #include "src/ast/scalar_constructor_expression.h"
 #include "src/ast/type_constructor_expression.h"
 #include "src/ast/variable.h"
+#include "src/program.h"
 #include "src/type/array_type.h"
 #include "src/type/f32_type.h"
 #include "src/writer/msl/generator_impl.h"
diff --git a/src/writer/msl/generator_impl_return_test.cc b/src/writer/msl/generator_impl_return_test.cc
index f881498..342600c 100644
--- a/src/writer/msl/generator_impl_return_test.cc
+++ b/src/writer/msl/generator_impl_return_test.cc
@@ -17,8 +17,8 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/return_statement.h"
+#include "src/program.h"
 #include "src/writer/msl/generator_impl.h"
 #include "src/writer/msl/test_helper.h"
 
diff --git a/src/writer/msl/generator_impl_switch_test.cc b/src/writer/msl/generator_impl_switch_test.cc
index 435a1fd..42f4a8b 100644
--- a/src/writer/msl/generator_impl_switch_test.cc
+++ b/src/writer/msl/generator_impl_switch_test.cc
@@ -18,9 +18,9 @@
 #include "src/ast/break_statement.h"
 #include "src/ast/case_statement.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/sint_literal.h"
 #include "src/ast/switch_statement.h"
+#include "src/program.h"
 #include "src/type/i32_type.h"
 #include "src/writer/msl/generator_impl.h"
 #include "src/writer/msl/test_helper.h"
diff --git a/src/writer/msl/generator_impl_test.cc b/src/writer/msl/generator_impl_test.cc
index 183c08d..765205e 100644
--- a/src/writer/msl/generator_impl_test.cc
+++ b/src/writer/msl/generator_impl_test.cc
@@ -20,12 +20,12 @@
 #include "gtest/gtest.h"
 #include "src/ast/function.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/pipeline_stage.h"
 #include "src/ast/stage_decoration.h"
 #include "src/ast/struct.h"
 #include "src/ast/struct_member.h"
 #include "src/ast/struct_member_offset_decoration.h"
+#include "src/program.h"
 #include "src/type/alias_type.h"
 #include "src/type/array_type.h"
 #include "src/type/bool_type.h"
diff --git a/src/writer/msl/generator_impl_type_test.cc b/src/writer/msl/generator_impl_type_test.cc
index 74dcff6..ce9f485 100644
--- a/src/writer/msl/generator_impl_type_test.cc
+++ b/src/writer/msl/generator_impl_type_test.cc
@@ -13,13 +13,13 @@
 // limitations under the License.
 
 #include "gtest/gtest.h"
-#include "src/ast/module.h"
 #include "src/ast/struct.h"
 #include "src/ast/struct_block_decoration.h"
 #include "src/ast/struct_decoration.h"
 #include "src/ast/struct_member.h"
 #include "src/ast/struct_member_decoration.h"
 #include "src/ast/struct_member_offset_decoration.h"
+#include "src/program.h"
 #include "src/type/access_control_type.h"
 #include "src/type/array_type.h"
 #include "src/type/bool_type.h"
diff --git a/src/writer/msl/generator_impl_unary_op_test.cc b/src/writer/msl/generator_impl_unary_op_test.cc
index 3a689ca..40e4aa9 100644
--- a/src/writer/msl/generator_impl_unary_op_test.cc
+++ b/src/writer/msl/generator_impl_unary_op_test.cc
@@ -17,8 +17,8 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/unary_op_expression.h"
+#include "src/program.h"
 #include "src/writer/msl/generator_impl.h"
 #include "src/writer/msl/test_helper.h"
 
diff --git a/src/writer/msl/generator_impl_variable_decl_statement_test.cc b/src/writer/msl/generator_impl_variable_decl_statement_test.cc
index da4be9b..0d72000 100644
--- a/src/writer/msl/generator_impl_variable_decl_statement_test.cc
+++ b/src/writer/msl/generator_impl_variable_decl_statement_test.cc
@@ -17,7 +17,6 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/identifier_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/struct.h"
 #include "src/ast/struct_decoration.h"
 #include "src/ast/struct_member.h"
@@ -25,6 +24,7 @@
 #include "src/ast/struct_member_offset_decoration.h"
 #include "src/ast/variable.h"
 #include "src/ast/variable_decl_statement.h"
+#include "src/program.h"
 #include "src/type/array_type.h"
 #include "src/type/f32_type.h"
 #include "src/type/matrix_type.h"
diff --git a/src/writer/msl/test_helper.h b/src/writer/msl/test_helper.h
index 1d1f0d5..5d91a3a 100644
--- a/src/writer/msl/test_helper.h
+++ b/src/writer/msl/test_helper.h
@@ -20,7 +20,7 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/builder.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/type_determiner.h"
 #include "src/writer/msl/generator_impl.h"
 
@@ -30,12 +30,12 @@
 
 /// Helper class for testing
 template <typename BASE>
-class TestHelperBase : public BASE, public ast::BuilderWithModule {
+class TestHelperBase : public BASE, public ast::BuilderWithProgram {
  public:
-  TestHelperBase() : td(mod) {}
+  TestHelperBase() : td(program) {}
   ~TestHelperBase() = default;
 
-  /// Builds and returns a GeneratorImpl from the module.
+  /// Builds and returns a GeneratorImpl from the program.
   /// @note The generator is only built once. Multiple calls to Build() will
   /// return the same GeneratorImpl without rebuilding.
   /// @return the built generator
@@ -43,7 +43,7 @@
     if (gen_) {
       return *gen_;
     }
-    gen_ = std::make_unique<GeneratorImpl>(mod);
+    gen_ = std::make_unique<GeneratorImpl>(program);
     return *gen_;
   }
 
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index d79f622..8c0e43b 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -285,7 +285,8 @@
 
 Builder::AccessorInfo::~AccessorInfo() {}
 
-Builder::Builder(ast::Module* mod) : mod_(mod), scope_stack_({}) {}
+Builder::Builder(const Program* program)
+    : program_(program), scope_stack_({}) {}
 
 Builder::~Builder() = default;
 
@@ -296,13 +297,13 @@
                     {Operand::Int(SpvAddressingModelLogical),
                      Operand::Int(SpvMemoryModelGLSL450)});
 
-  for (auto* var : mod_->global_variables()) {
+  for (auto* var : program_->global_variables()) {
     if (!GenerateGlobalVariable(var)) {
       return false;
     }
   }
 
-  for (auto* func : mod_->Functions()) {
+  for (auto* func : program_->Functions()) {
     if (!GenerateFunction(func)) {
       return false;
     }
@@ -447,8 +448,9 @@
     return false;
   }
 
-  OperandList operands = {Operand::Int(stage), Operand::Int(id),
-                          Operand::String(mod_->SymbolToName(func->symbol()))};
+  OperandList operands = {
+      Operand::Int(stage), Operand::Int(id),
+      Operand::String(program_->SymbolToName(func->symbol()))};
 
   for (const auto* var : func->referenced_module_variables()) {
     // For SPIR-V 1.3 we only output Input/output variables. If we update to
@@ -461,7 +463,7 @@
     uint32_t var_id;
     if (!scope_stack_.get(var->symbol(), &var_id)) {
       error_ = "unable to find ID for global variable: " +
-               mod_->SymbolToName(var->symbol());
+               program_->SymbolToName(var->symbol());
       return false;
     }
 
@@ -541,7 +543,7 @@
 
   push_debug(spv::Op::OpName,
              {Operand::Int(func_id),
-              Operand::String(mod_->SymbolToName(func->symbol()))});
+              Operand::String(program_->SymbolToName(func->symbol()))});
 
   auto ret_id = GenerateTypeIfNeeded(func->return_type());
   if (ret_id == 0) {
@@ -567,7 +569,7 @@
 
     push_debug(spv::Op::OpName,
                {Operand::Int(param_id),
-                Operand::String(mod_->SymbolToName(param->symbol()))});
+                Operand::String(program_->SymbolToName(param->symbol()))});
     params.push_back(Instruction{spv::Op::OpFunctionParameter,
                                  {Operand::Int(param_type_id), param_op}});
 
@@ -658,7 +660,7 @@
 
   push_debug(spv::Op::OpName,
              {Operand::Int(var_id),
-              Operand::String(mod_->SymbolToName(var->symbol()))});
+              Operand::String(program_->SymbolToName(var->symbol()))});
 
   // TODO(dsinclair) We could detect if the constructor is fully const and emit
   // an initializer value for the variable instead of doing the OpLoad.
@@ -710,7 +712,7 @@
     }
     push_debug(spv::Op::OpName,
                {Operand::Int(init_id),
-                Operand::String(mod_->SymbolToName(var->symbol()))});
+                Operand::String(program_->SymbolToName(var->symbol()))});
 
     scope_stack_.set_global(var->symbol(), init_id);
     spirv_id_to_variable_[init_id] = var;
@@ -732,7 +734,7 @@
 
   push_debug(spv::Op::OpName,
              {Operand::Int(var_id),
-              Operand::String(mod_->SymbolToName(var->symbol()))});
+              Operand::String(program_->SymbolToName(var->symbol()))});
 
   OperandList ops = {Operand::Int(type_id), result,
                      Operand::Int(ConvertStorageClass(sc))};
@@ -913,7 +915,7 @@
   }
 
   // TODO(dsinclair): Swizzle stuff
-  auto swiz = mod_->SymbolToName(expr->member()->symbol());
+  auto swiz = program_->SymbolToName(expr->member()->symbol());
   // Single element swizzle is either an access chain or a composite extract
   if (swiz.size() == 1) {
     auto val = IndexFromName(swiz[0]);
@@ -1121,7 +1123,7 @@
   }
 
   error_ = "unable to find variable with identifier: " +
-           mod_->SymbolToName(expr->symbol());
+           program_->SymbolToName(expr->symbol());
   return 0;
 }
 
@@ -1814,7 +1816,7 @@
   auto func_id = func_symbol_to_id_[ident->symbol()];
   if (func_id == 0) {
     error_ = "unable to find called function: " +
-             mod_->SymbolToName(ident->symbol());
+             program_->SymbolToName(ident->symbol());
     return 0;
   }
   ops.push_back(Operand::Int(func_id));
@@ -1946,7 +1948,7 @@
     auto inst_id =
         intrinsic_to_glsl_method(ident->result_type(), ident->intrinsic());
     if (inst_id == 0) {
-      error_ = "unknown method " + mod_->SymbolToName(ident->symbol());
+      error_ = "unknown method " + program_->SymbolToName(ident->symbol());
       return 0;
     }
 
@@ -1958,7 +1960,7 @@
 
   if (op == spv::Op::OpNop) {
     error_ = "unable to determine operator for: " +
-             mod_->SymbolToName(ident->symbol());
+             program_->SymbolToName(ident->symbol());
     return 0;
   }
 
@@ -2041,8 +2043,10 @@
   // to calling append_result_type_and_id_to_spirv_params().
   auto append_result_type_and_id_to_spirv_params_for_read = [&]() {
     if (texture_type->Is<type::DepthTexture>()) {
-      auto* f32 = mod_->create<type::F32>();
-      auto* spirv_result_type = mod_->create<type::Vector>(f32, 4);
+      // TODO(https://crbug.com/tint/390): Remove this const_cast hack!
+      auto* f32 = const_cast<Program*>(program_)->create<type::F32>();
+      auto* spirv_result_type =
+          const_cast<Program*>(program_)->create<type::Vector>(f32, 4);
       auto spirv_result = result_op();
       post_emission = [=] {
         return push_function_inst(
@@ -2073,8 +2077,10 @@
           // OpImageQuerySize[Lod].
           auto* element_type = ElementTypeOf(call->result_type());
           auto spirv_result = result_op();
+          // TODO(https://crbug.com/tint/390): Remove this const_cast hack!
           auto* spirv_result_type =
-              mod_->create<type::Vector>(element_type, spirv_result_width);
+              const_cast<Program*>(program_)->create<type::Vector>(
+                  element_type, spirv_result_width);
           if (swizzle.size() > 1) {
             post_emission = [=] {
               OperandList operands{
@@ -2192,7 +2198,9 @@
         op = spv::Op::OpImageQuerySizeLod;
         spirv_params.emplace_back(gen_param(pidx.level));
       } else {
-        ast::SintLiteral i32_0(Source{}, mod_->create<type::I32>(), 0);
+        // TODO(https://crbug.com/tint/390): Remove this const_cast hack!
+        ast::SintLiteral i32_0(
+            Source{}, const_cast<Program*>(program_)->create<type::I32>(), 0);
         op = spv::Op::OpImageQuerySizeLod;
         spirv_params.emplace_back(
             Operand::Int(GenerateLiteralIfNeeded(nullptr, &i32_0)));
@@ -2227,7 +2235,9 @@
           texture_type->Is<type::StorageTexture>()) {
         op = spv::Op::OpImageQuerySize;
       } else {
-        ast::SintLiteral i32_0(Source{}, mod_->create<type::I32>(), 0);
+        // TODO(https://crbug.com/tint/390): Remove this const_cast hack!
+        ast::SintLiteral i32_0(
+            Source{}, const_cast<Program*>(program_)->create<type::I32>(), 0);
         op = spv::Op::OpImageQuerySizeLod;
         spirv_params.emplace_back(
             Operand::Int(GenerateLiteralIfNeeded(nullptr, &i32_0)));
@@ -2306,7 +2316,8 @@
       if (call->params()[pidx.level]->result_type()->Is<type::I32>()) {
         // Depth textures have i32 parameters for the level, but SPIR-V expects
         // F32. Cast.
-        auto* f32 = mod_->create<type::F32>();
+        // TODO(https://crbug.com/tint/390): Remove this const_cast hack!
+        auto* f32 = const_cast<Program*>(program_)->create<type::F32>();
         ast::TypeConstructorExpression cast(Source{}, f32,
                                             {call->params()[pidx.level]});
         level = Operand::Int(GenerateExpression(&cast));
@@ -2373,7 +2384,7 @@
 
   if (op == spv::Op::OpNop) {
     error_ = "unable to determine operator for: " +
-             mod_->SymbolToName(ident->symbol());
+             program_->SymbolToName(ident->symbol());
     return false;
   }
 
@@ -2992,9 +3003,10 @@
   auto* impl = struct_type->impl();
 
   if (struct_type->symbol().IsValid()) {
-    push_debug(spv::Op::OpName,
-               {Operand::Int(struct_id),
-                Operand::String(mod_->SymbolToName(struct_type->symbol()))});
+    push_debug(
+        spv::Op::OpName,
+        {Operand::Int(struct_id),
+         Operand::String(program_->SymbolToName(struct_type->symbol()))});
   }
 
   OperandList ops;
@@ -3037,7 +3049,7 @@
                                        ast::StructMember* member) {
   push_debug(spv::Op::OpMemberName,
              {Operand::Int(struct_id), Operand::Int(idx),
-              Operand::String(mod_->SymbolToName(member->symbol()))});
+              Operand::String(program_->SymbolToName(member->symbol()))});
 
   bool has_layout = false;
   for (auto* deco : member->decorations()) {
diff --git a/src/writer/spirv/builder.h b/src/writer/spirv/builder.h
index 9a76a0d..aa6590f 100644
--- a/src/writer/spirv/builder.h
+++ b/src/writer/spirv/builder.h
@@ -37,13 +37,13 @@
 #include "src/ast/literal.h"
 #include "src/ast/loop_statement.h"
 #include "src/ast/member_accessor_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/return_statement.h"
 #include "src/ast/struct_member.h"
 #include "src/ast/switch_statement.h"
 #include "src/ast/type_constructor_expression.h"
 #include "src/ast/unary_op_expression.h"
 #include "src/ast/variable_decl_statement.h"
+#include "src/program.h"
 #include "src/scope_stack.h"
 #include "src/type/access_control_type.h"
 #include "src/type/array_type.h"
@@ -59,7 +59,7 @@
 namespace writer {
 namespace spirv {
 
-/// Builder class to create SPIR-V instructions from a module.
+/// Builder class to create SPIR-V instructions from a program.
 class Builder {
  public:
   /// Contains information for generating accessor chains
@@ -82,11 +82,11 @@
   };
 
   /// Constructor
-  /// @param mod the module to generate from
-  explicit Builder(ast::Module* mod);
+  /// @param program the program to generate from
+  explicit Builder(const Program* program);
   ~Builder();
 
-  /// Generates the SPIR-V instructions for the given module
+  /// Generates the SPIR-V instructions for the given program
   /// @returns true if the SPIR-V was successfully built
   bool Build();
 
@@ -98,7 +98,7 @@
   /// @returns the number of uint32_t's needed to make up the results
   uint32_t total_size() const;
 
-  /// @returns the id bound for this module
+  /// @returns the id bound for this program
   uint32_t id_bound() const { return next_id_; }
 
   /// @returns the next id to be used
@@ -487,7 +487,7 @@
   /// automatically.
   Operand result_op();
 
-  ast::Module* mod_;
+  const Program* program_;
   std::string error_;
   uint32_t next_id_ = 1;
   uint32_t current_label_id_ = 0;
diff --git a/src/writer/spirv/builder_accessor_expression_test.cc b/src/writer/spirv/builder_accessor_expression_test.cc
index 5551098..c9abc71 100644
--- a/src/writer/spirv/builder_accessor_expression_test.cc
+++ b/src/writer/spirv/builder_accessor_expression_test.cc
@@ -19,7 +19,6 @@
 #include "src/ast/float_literal.h"
 #include "src/ast/identifier_expression.h"
 #include "src/ast/member_accessor_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/scalar_constructor_expression.h"
 #include "src/ast/sint_literal.h"
 #include "src/ast/struct.h"
@@ -27,6 +26,7 @@
 #include "src/ast/type_constructor_expression.h"
 #include "src/ast/uint_literal.h"
 #include "src/ast/variable.h"
+#include "src/program.h"
 #include "src/type/array_type.h"
 #include "src/type/f32_type.h"
 #include "src/type/i32_type.h"
diff --git a/src/writer/spirv/builder_bitcast_expression_test.cc b/src/writer/spirv/builder_bitcast_expression_test.cc
index 33a717a..80c564b 100644
--- a/src/writer/spirv/builder_bitcast_expression_test.cc
+++ b/src/writer/spirv/builder_bitcast_expression_test.cc
@@ -15,8 +15,8 @@
 #include "gtest/gtest.h"
 #include "src/ast/bitcast_expression.h"
 #include "src/ast/float_literal.h"
-#include "src/ast/module.h"
 #include "src/ast/scalar_constructor_expression.h"
+#include "src/program.h"
 #include "src/type/f32_type.h"
 #include "src/type/u32_type.h"
 #include "src/type_determiner.h"
diff --git a/src/writer/spirv/builder_global_variable_test.cc b/src/writer/spirv/builder_global_variable_test.cc
index ec0838a..f9214b8 100644
--- a/src/writer/spirv/builder_global_variable_test.cc
+++ b/src/writer/spirv/builder_global_variable_test.cc
@@ -23,13 +23,13 @@
 #include "src/ast/float_literal.h"
 #include "src/ast/group_decoration.h"
 #include "src/ast/location_decoration.h"
-#include "src/ast/module.h"
 #include "src/ast/scalar_constructor_expression.h"
 #include "src/ast/storage_class.h"
 #include "src/ast/struct.h"
 #include "src/ast/type_constructor_expression.h"
 #include "src/ast/variable.h"
 #include "src/ast/variable_decoration.h"
+#include "src/program.h"
 #include "src/type/access_control_type.h"
 #include "src/type/bool_type.h"
 #include "src/type/f32_type.h"
diff --git a/src/writer/spirv/builder_test.cc b/src/writer/spirv/builder_test.cc
index 9cedea7..3498566 100644
--- a/src/writer/spirv/builder_test.cc
+++ b/src/writer/spirv/builder_test.cc
@@ -19,7 +19,7 @@
 #include "gtest/gtest.h"
 #include "spirv/unified1/spirv.h"
 #include "spirv/unified1/spirv.hpp11"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/writer/spirv/spv_dump.h"
 #include "src/writer/spirv/test_helper.h"
 
diff --git a/src/writer/spirv/generator.cc b/src/writer/spirv/generator.cc
index ba367c5..4163e57 100644
--- a/src/writer/spirv/generator.cc
+++ b/src/writer/spirv/generator.cc
@@ -20,13 +20,8 @@
 namespace writer {
 namespace spirv {
 
-Generator::Generator(ast::Module module)
-    : module_(std::move(module)),
-      builder_(std::make_unique<Builder>(&module_)),
-      writer_(std::make_unique<BinaryWriter>()) {}
-
-Generator::Generator(Program* program)
-    : builder_(std::make_unique<Builder>(&program->module)),
+Generator::Generator(const Program* program)
+    : builder_(std::make_unique<Builder>(program)),
       writer_(std::make_unique<BinaryWriter>()) {}
 
 Generator::~Generator() = default;
diff --git a/src/writer/spirv/generator.h b/src/writer/spirv/generator.h
index 82bff48..c85fe4f 100644
--- a/src/writer/spirv/generator.h
+++ b/src/writer/spirv/generator.h
@@ -19,7 +19,6 @@
 #include <string>
 #include <vector>
 
-#include "src/ast/module.h"
 #include "src/program.h"
 #include "src/writer/spirv/binary_writer.h"
 #include "src/writer/spirv/builder.h"
@@ -29,16 +28,12 @@
 namespace writer {
 namespace spirv {
 
-/// Class to generate SPIR-V from a Tint module
+/// Class to generate SPIR-V from a Tint program
 class Generator : public writer::Writer {
  public:
   /// Constructor
-  /// @param module the module to convert
-  explicit Generator(ast::Module module);
-
-  /// Constructor
   /// @param program the program to convert
-  explicit Generator(Program* program);
+  explicit Generator(const Program* program);
 
   /// Destructor
   ~Generator() override;
@@ -58,7 +53,6 @@
   const std::vector<uint32_t>& result() const { return writer_->result(); }
 
  private:
-  ast::Module module_;
   std::unique_ptr<Builder> builder_;
   std::unique_ptr<BinaryWriter> writer_;
 };
diff --git a/src/writer/spirv/test_helper.h b/src/writer/spirv/test_helper.h
index 6ee8b64..52c1aae 100644
--- a/src/writer/spirv/test_helper.h
+++ b/src/writer/spirv/test_helper.h
@@ -20,7 +20,7 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/builder.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/type_determiner.h"
 #include "src/writer/spirv/builder.h"
 
@@ -30,12 +30,12 @@
 
 /// Helper class for testing
 template <typename BASE>
-class TestHelperBase : public ast::BuilderWithModule, public BASE {
+class TestHelperBase : public ast::BuilderWithProgram, public BASE {
  public:
-  TestHelperBase() : td(mod) {}
+  TestHelperBase() : td(program) {}
   ~TestHelperBase() override = default;
 
-  /// Builds and returns a spirv::Builder from the module.
+  /// Builds and returns a spirv::Builder from the program.
   /// @note The spirv::Builder is only built once. Multiple calls to Build()
   /// will return the same spirv::Builder without rebuilding.
   /// @return the built spirv::Builder
@@ -43,7 +43,7 @@
     if (spirv_builder) {
       return *spirv_builder;
     }
-    spirv_builder = std::make_unique<spirv::Builder>(mod);
+    spirv_builder = std::make_unique<spirv::Builder>(program);
     return *spirv_builder;
   }
 
diff --git a/src/writer/wgsl/generator.cc b/src/writer/wgsl/generator.cc
index 368b5ef..5fc91cc 100644
--- a/src/writer/wgsl/generator.cc
+++ b/src/writer/wgsl/generator.cc
@@ -20,12 +20,8 @@
 namespace writer {
 namespace wgsl {
 
-Generator::Generator(ast::Module module)
-    : module_(std::move(module)),
-      impl_(std::make_unique<GeneratorImpl>(&module_)) {}
-
-Generator::Generator(Program* program)
-    : impl_(std::make_unique<GeneratorImpl>(&program->module)) {}
+Generator::Generator(const Program* program)
+    : impl_(std::make_unique<GeneratorImpl>(program)) {}
 
 Generator::~Generator() = default;
 
diff --git a/src/writer/wgsl/generator.h b/src/writer/wgsl/generator.h
index 3ed31ec..1c83faf 100644
--- a/src/writer/wgsl/generator.h
+++ b/src/writer/wgsl/generator.h
@@ -30,12 +30,8 @@
 class Generator : public Text {
  public:
   /// Constructor
-  /// @param module the module to convert
-  explicit Generator(ast::Module module);
-
-  /// Constructor
   /// @param program the program to convert
-  explicit Generator(Program* program);
+  explicit Generator(const Program* program);
 
   /// Destructor
   ~Generator() override;
@@ -58,7 +54,6 @@
   std::string error() const;
 
  private:
-  ast::Module module_;
   std::unique_ptr<GeneratorImpl> impl_;
 };
 
diff --git a/src/writer/wgsl/generator_impl.cc b/src/writer/wgsl/generator_impl.cc
index 520a595..3b26bec 100644
--- a/src/writer/wgsl/generator_impl.cc
+++ b/src/writer/wgsl/generator_impl.cc
@@ -78,30 +78,30 @@
 namespace writer {
 namespace wgsl {
 
-GeneratorImpl::GeneratorImpl(ast::Module* module)
-    : TextGenerator(), module_(*module) {}
+GeneratorImpl::GeneratorImpl(const Program* program)
+    : TextGenerator(), program_(program) {}
 
 GeneratorImpl::~GeneratorImpl() = default;
 
 bool GeneratorImpl::Generate() {
-  for (auto* const ty : module_.constructed_types()) {
+  for (auto* const ty : program_->constructed_types()) {
     if (!EmitConstructedType(ty)) {
       return false;
     }
   }
-  if (!module_.constructed_types().empty())
+  if (!program_->constructed_types().empty())
     out_ << std::endl;
 
-  for (auto* var : module_.global_variables()) {
+  for (auto* var : program_->global_variables()) {
     if (!EmitVariable(var)) {
       return false;
     }
   }
-  if (!module_.global_variables().empty()) {
+  if (!program_->global_variables().empty()) {
     out_ << std::endl;
   }
 
-  for (auto* func : module_.Functions()) {
+  for (auto* func : program_->Functions()) {
     if (!EmitFunction(func)) {
       return false;
     }
@@ -113,7 +113,7 @@
 
 bool GeneratorImpl::GenerateEntryPoint(ast::PipelineStage stage,
                                        const std::string& name) {
-  auto* func = module_.Functions().Find(module_.GetSymbol(name), stage);
+  auto* func = program_->Functions().Find(program_->GetSymbol(name), stage);
   if (func == nullptr) {
     error_ = "Unable to find requested entry point: " + name;
     return false;
@@ -121,18 +121,18 @@
 
   // TODO(dsinclair): We always emit constructed types even if they aren't
   // strictly needed
-  for (auto* const ty : module_.constructed_types()) {
+  for (auto* const ty : program_->constructed_types()) {
     if (!EmitConstructedType(ty)) {
       return false;
     }
   }
-  if (!module_.constructed_types().empty()) {
+  if (!program_->constructed_types().empty()) {
     out_ << std::endl;
   }
 
   // TODO(dsinclair): This should be smarter and only emit needed const
   // variables
-  for (auto* var : module_.global_variables()) {
+  for (auto* var : program_->global_variables()) {
     if (!var->is_const()) {
       continue;
     }
@@ -152,8 +152,8 @@
     out_ << std::endl;
   }
 
-  for (auto* f : module_.Functions()) {
-    if (!f->HasAncestorEntryPoint(module_.GetSymbol(name))) {
+  for (auto* f : program_->Functions()) {
+    if (!f->HasAncestorEntryPoint(program_->GetSymbol(name))) {
       continue;
     }
 
@@ -174,7 +174,7 @@
 bool GeneratorImpl::EmitConstructedType(const type::Type* ty) {
   make_indent();
   if (auto* alias = ty->As<type::Alias>()) {
-    out_ << "type " << module_.SymbolToName(alias->symbol()) << " = ";
+    out_ << "type " << program_->SymbolToName(alias->symbol()) << " = ";
     if (!EmitType(alias->type())) {
       return false;
     }
@@ -337,7 +337,7 @@
 
 bool GeneratorImpl::EmitIdentifier(ast::IdentifierExpression* expr) {
   auto* ident = expr->As<ast::IdentifierExpression>();
-  out_ << module_.SymbolToName(ident->symbol());
+  out_ << program_->SymbolToName(ident->symbol());
   return true;
 }
 
@@ -360,7 +360,7 @@
   }
 
   make_indent();
-  out_ << "fn " << module_.SymbolToName(func->symbol()) << "(";
+  out_ << "fn " << program_->SymbolToName(func->symbol()) << "(";
 
   bool first = true;
   for (auto* v : func->params()) {
@@ -369,7 +369,7 @@
     }
     first = false;
 
-    out_ << module_.SymbolToName(v->symbol()) << " : ";
+    out_ << program_->SymbolToName(v->symbol()) << " : ";
 
     if (!EmitType(v->type())) {
       return false;
@@ -417,7 +417,7 @@
     }
     return true;
   } else if (auto* alias = type->As<type::Alias>()) {
-    out_ << module_.SymbolToName(alias->symbol());
+    out_ << program_->SymbolToName(alias->symbol());
   } else if (auto* ary = type->As<type::Array>()) {
     for (auto* deco : ary->decorations()) {
       if (auto* stride = deco->As<ast::StrideDecoration>()) {
@@ -461,7 +461,7 @@
   } else if (auto* str = type->As<type::Struct>()) {
     // The struct, as a type, is just the name. We should have already emitted
     // the declaration through a call to |EmitStructType| earlier.
-    out_ << module_.SymbolToName(str->symbol());
+    out_ << program_->SymbolToName(str->symbol());
   } else if (auto* texture = type->As<type::Texture>()) {
     out_ << "texture_";
     if (texture->Is<type::DepthTexture>()) {
@@ -549,7 +549,8 @@
     deco->to_str(out_, 0);
     out_ << "]]" << std::endl;
   }
-  out_ << "struct " << module_.SymbolToName(str->symbol()) << " {" << std::endl;
+  out_ << "struct " << program_->SymbolToName(str->symbol()) << " {"
+       << std::endl;
 
   increment_indent();
   for (auto* mem : impl->members()) {
@@ -562,7 +563,7 @@
       out_ << "[[offset(" << offset->offset() << ")]]" << std::endl;
     }
     make_indent();
-    out_ << module_.SymbolToName(mem->symbol()) << " : ";
+    out_ << program_->SymbolToName(mem->symbol()) << " : ";
     if (!EmitType(mem->type())) {
       return false;
     }
@@ -592,7 +593,7 @@
     }
   }
 
-  out_ << " " << module_.SymbolToName(var->symbol()) << " : ";
+  out_ << " " << program_->SymbolToName(var->symbol()) << " : ";
   if (!EmitType(var->type())) {
     return false;
   }
diff --git a/src/writer/wgsl/generator_impl.h b/src/writer/wgsl/generator_impl.h
index 1b3d568..fa4603b 100644
--- a/src/writer/wgsl/generator_impl.h
+++ b/src/writer/wgsl/generator_impl.h
@@ -33,13 +33,13 @@
 #include "src/ast/if_statement.h"
 #include "src/ast/loop_statement.h"
 #include "src/ast/member_accessor_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/return_statement.h"
 #include "src/ast/scalar_constructor_expression.h"
 #include "src/ast/switch_statement.h"
 #include "src/ast/type_constructor_expression.h"
 #include "src/ast/unary_op_expression.h"
 #include "src/ast/variable.h"
+#include "src/program.h"
 #include "src/type/storage_texture_type.h"
 #include "src/type/struct_type.h"
 #include "src/type/type.h"
@@ -53,8 +53,8 @@
 class GeneratorImpl : public TextGenerator {
  public:
   /// Constructor
-  /// @param mod the module to generate
-  explicit GeneratorImpl(ast::Module* mod);
+  /// @param program the program
+  explicit GeneratorImpl(const Program* program);
   ~GeneratorImpl();
 
   /// Generates the result data
@@ -205,7 +205,7 @@
   bool EmitVariableDecorations(ast::Variable* var);
 
  private:
-  ast::Module& module_;
+  Program const* const program_;
 };
 
 }  // namespace wgsl
diff --git a/src/writer/wgsl/generator_impl_function_test.cc b/src/writer/wgsl/generator_impl_function_test.cc
index 0176f7b..7e4f2af 100644
--- a/src/writer/wgsl/generator_impl_function_test.cc
+++ b/src/writer/wgsl/generator_impl_function_test.cc
@@ -16,7 +16,6 @@
 #include "src/ast/discard_statement.h"
 #include "src/ast/function.h"
 #include "src/ast/member_accessor_expression.h"
-#include "src/ast/module.h"
 #include "src/ast/pipeline_stage.h"
 #include "src/ast/return_statement.h"
 #include "src/ast/stage_decoration.h"
@@ -25,6 +24,7 @@
 #include "src/ast/variable.h"
 #include "src/ast/variable_decl_statement.h"
 #include "src/ast/workgroup_decoration.h"
+#include "src/program.h"
 #include "src/type/access_control_type.h"
 #include "src/type/f32_type.h"
 #include "src/type/i32_type.h"
diff --git a/src/writer/wgsl/generator_impl_test.cc b/src/writer/wgsl/generator_impl_test.cc
index bf88db1..449e795 100644
--- a/src/writer/wgsl/generator_impl_test.cc
+++ b/src/writer/wgsl/generator_impl_test.cc
@@ -18,7 +18,7 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/function.h"
-#include "src/ast/module.h"
+#include "src/program.h"
 #include "src/type/void_type.h"
 #include "src/writer/wgsl/test_helper.h"
 
diff --git a/src/writer/wgsl/test_helper.h b/src/writer/wgsl/test_helper.h
index 6507d32..5195c04 100644
--- a/src/writer/wgsl/test_helper.h
+++ b/src/writer/wgsl/test_helper.h
@@ -29,13 +29,13 @@
 
 /// Helper class for testing
 template <typename BASE>
-class TestHelperBase : public BASE, public ast::BuilderWithModule {
+class TestHelperBase : public BASE, public ast::BuilderWithProgram {
  public:
-  TestHelperBase() : td(mod) {}
+  TestHelperBase() : td(program) {}
 
   ~TestHelperBase() = default;
 
-  /// Builds and returns a GeneratorImpl from the module.
+  /// Builds and returns a GeneratorImpl from the program.
   /// @note The generator is only built once. Multiple calls to Build() will
   /// return the same GeneratorImpl without rebuilding.
   /// @return the built generator
@@ -43,7 +43,7 @@
     if (gen_) {
       return *gen_;
     }
-    gen_ = std::make_unique<GeneratorImpl>(mod);
+    gen_ = std::make_unique<GeneratorImpl>(program);
     return *gen_;
   }
 
diff --git a/src/writer/writer.h b/src/writer/writer.h
index 7aa7a97..1f6a18e 100644
--- a/src/writer/writer.h
+++ b/src/writer/writer.h
@@ -17,8 +17,8 @@
 
 #include <string>
 
-#include "src/ast/module.h"
 #include "src/ast/pipeline_stage.h"
+#include "src/program.h"
 
 namespace tint {
 namespace writer {