[msl-writer] Cleanups and refactors.

This CL cleans up some interfaces and methods in the MSL generator and
generator impl classes.

Bug: tint:8
Change-Id: I9aabeb1ecb69baeaa9cb6bbc15e313806923dddc
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/25163
Reviewed-by: David Neto <dneto@google.com>
diff --git a/src/writer/msl/generator.cc b/src/writer/msl/generator.cc
index a62c706..ce3c1a0 100644
--- a/src/writer/msl/generator.cc
+++ b/src/writer/msl/generator.cc
@@ -20,12 +20,13 @@
 namespace writer {
 namespace msl {
 
-Generator::Generator(ast::Module module) : Text(std::move(module)) {}
+Generator::Generator(ast::Module module)
+    : Text(std::move(module)), impl_(&module_) {}
 
 Generator::~Generator() = default;
 
 bool Generator::Generate() {
-  auto ret = impl_.Generate(module_);
+  auto ret = impl_.Generate();
   if (!ret) {
     error_ = impl_.error();
   }
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc
index dbfff5c..b3af01d 100644
--- a/src/writer/msl/generator_impl.cc
+++ b/src/writer/msl/generator_impl.cc
@@ -81,14 +81,10 @@
 
 }  // namespace
 
-GeneratorImpl::GeneratorImpl() = default;
+GeneratorImpl::GeneratorImpl(ast::Module* module) : module_(module) {}
 
 GeneratorImpl::~GeneratorImpl() = default;
 
-void GeneratorImpl::set_module_for_testing(ast::Module* mod) {
-  module_ = mod;
-}
-
 std::string GeneratorImpl::generate_name(const std::string& prefix) {
   std::string name = prefix;
   uint32_t i = 0;
@@ -100,25 +96,23 @@
   return name;
 }
 
-bool GeneratorImpl::Generate(const ast::Module& module) {
-  module_ = &module;
-
+bool GeneratorImpl::Generate() {
   out_ << "#include <metal_stdlib>" << std::endl << std::endl;
 
-  for (const auto& global : module.global_variables()) {
+  for (const auto& global : module_->global_variables()) {
     global_variables_.set(global->name(), global.get());
   }
 
-  for (auto* const alias : module.alias_types()) {
+  for (auto* const alias : module_->alias_types()) {
     if (!EmitAliasType(alias)) {
       return false;
     }
   }
-  if (!module.alias_types().empty()) {
+  if (!module_->alias_types().empty()) {
     out_ << std::endl;
   }
 
-  for (const auto& var : module.global_variables()) {
+  for (const auto& var : module_->global_variables()) {
     if (!var->is_const()) {
       continue;
     }
@@ -127,26 +121,25 @@
     }
   }
 
-  for (const auto& ep : module.entry_points()) {
+  for (const auto& ep : module_->entry_points()) {
     if (!EmitEntryPointData(ep.get())) {
       return false;
     }
   }
 
-  for (const auto& func : module.functions()) {
+  for (const auto& func : module_->functions()) {
     if (!EmitFunction(func.get())) {
       return false;
     }
   }
 
-  for (const auto& ep : module.entry_points()) {
+  for (const auto& ep : module_->entry_points()) {
     if (!EmitEntryPointFunction(ep.get())) {
       return false;
     }
     out_ << std::endl;
   }
 
-  module_ = nullptr;
   return true;
 }
 
@@ -1126,6 +1119,17 @@
   return true;
 }
 
+bool GeneratorImpl::global_is_in_struct(ast::Variable* var) const {
+  bool in_or_out_struct_has_location =
+      var->IsDecorated() && var->AsDecorated()->HasLocationDecoration() &&
+      (var->storage_class() == ast::StorageClass::kInput ||
+       var->storage_class() == ast::StorageClass::kOutput);
+  bool in_struct_has_builtin =
+      var->IsDecorated() && var->AsDecorated()->HasBuiltinDecoration() &&
+      var->storage_class() == ast::StorageClass::kOutput;
+  return in_or_out_struct_has_location || in_struct_has_builtin;
+}
+
 bool GeneratorImpl::EmitIdentifier(ast::IdentifierExpression* expr) {
   auto* ident = expr->AsIdentifier();
   if (ident->has_path()) {
@@ -1136,14 +1140,7 @@
 
   ast::Variable* var = nullptr;
   if (global_variables_.get(ident->name(), &var)) {
-    bool in_or_out_struct_has_location =
-        var->IsDecorated() && var->AsDecorated()->HasLocationDecoration() &&
-        (var->storage_class() == ast::StorageClass::kInput ||
-         var->storage_class() == ast::StorageClass::kOutput);
-    bool in_struct_has_builtin =
-        var->IsDecorated() && var->AsDecorated()->HasBuiltinDecoration() &&
-        var->storage_class() == ast::StorageClass::kOutput;
-    if (in_or_out_struct_has_location || in_struct_has_builtin) {
+    if (global_is_in_struct(var)) {
       auto var_type = var->storage_class() == ast::StorageClass::kInput
                           ? VarType::kIn
                           : VarType::kOut;
diff --git a/src/writer/msl/generator_impl.h b/src/writer/msl/generator_impl.h
index 094ba80..5578a62 100644
--- a/src/writer/msl/generator_impl.h
+++ b/src/writer/msl/generator_impl.h
@@ -36,13 +36,12 @@
 class GeneratorImpl : public TextGenerator {
  public:
   /// Constructor
-  GeneratorImpl();
+  /// @param module the module to generate
+  explicit GeneratorImpl(ast::Module* module);
   ~GeneratorImpl();
 
-  /// Generates the result data
-  /// @param module the module to generate
   /// @returns true on successful generation; false otherwise
-  bool Generate(const ast::Module& module);
+  bool Generate();
 
   /// Calculates the alignment size of the given |type|. This returns 0
   /// for pointers as the size is unknown.
@@ -204,10 +203,6 @@
   /// @returns true if the zero value was successfully emitted.
   bool EmitZeroValue(ast::type::Type* type);
 
-  /// Sets the module for testing purposes
-  /// @param mod the module to set.
-  void set_module_for_testing(ast::Module* mod);
-
   /// Determines if any used module variable requires an input or output struct.
   /// @param func the function to check
   /// @returns true if an input or output struct is required.
@@ -218,6 +213,11 @@
   /// @returns the name
   std::string generate_name(const std::string& prefix);
 
+  /// Checks if the global variable is in an input or output struct
+  /// @param var the variable to check
+  /// @returns true if the global is in an input or output struct
+  bool global_is_in_struct(ast::Variable* var) const;
+
   /// Converts a builtin to an attribute name
   /// @param builtin the builtin to convert
   /// @returns the string name of the builtin or blank on error
@@ -228,6 +228,12 @@
 
  private:
   enum class VarType { kIn, kOut };
+
+  struct EntryPointData {
+    std::string struct_name;
+    std::string var_name;
+  };
+
   std::string current_ep_var_name(VarType type);
 
   Namer namer_;
@@ -237,10 +243,6 @@
   const ast::Module* module_ = nullptr;
   uint32_t loop_emission_counter_ = 0;
 
-  struct EntryPointData {
-    std::string struct_name;
-    std::string var_name;
-  };
   std::unordered_map<std::string, EntryPointData> ep_name_to_in_data_;
   std::unordered_map<std::string, EntryPointData> ep_name_to_out_data_;
 
diff --git a/src/writer/msl/generator_impl_alias_type_test.cc b/src/writer/msl/generator_impl_alias_type_test.cc
index faeeaaa..52fce9b 100644
--- a/src/writer/msl/generator_impl_alias_type_test.cc
+++ b/src/writer/msl/generator_impl_alias_type_test.cc
@@ -13,6 +13,7 @@
 // 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/ast/struct_member_decoration.h"
@@ -33,7 +34,8 @@
   ast::type::F32Type f32;
   ast::type::AliasType alias("a", &f32);
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitAliasType(&alias)) << g.error();
   EXPECT_EQ(g.result(), R"(typedef float a;
 )");
@@ -43,7 +45,8 @@
   ast::type::F32Type f32;
   ast::type::AliasType alias("float", &f32);
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitAliasType(&alias)) << g.error();
   EXPECT_EQ(g.result(), R"(typedef float float_tint_0;
 )");
@@ -68,7 +71,8 @@
   ast::type::StructType s(std::move(str));
   ast::type::AliasType alias("a", &s);
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitAliasType(&alias)) << g.error();
   EXPECT_EQ(g.result(), R"(typedef struct {
   float a;
diff --git a/src/writer/msl/generator_impl_array_accessor_test.cc b/src/writer/msl/generator_impl_array_accessor_test.cc
index 5957e00..bdcfa83 100644
--- a/src/writer/msl/generator_impl_array_accessor_test.cc
+++ b/src/writer/msl/generator_impl_array_accessor_test.cc
@@ -17,6 +17,7 @@
 #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/ast/type/i32_type.h"
@@ -37,7 +38,8 @@
 
   ast::ArrayAccessorExpression expr(std::move(ary), std::move(idx));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitExpression(&expr)) << g.error();
   EXPECT_EQ(g.result(), "ary[5]");
 }
@@ -48,7 +50,8 @@
 
   ast::ArrayAccessorExpression expr(std::move(ary), std::move(idx));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitArrayAccessor(&expr)) << g.error();
   EXPECT_EQ(g.result(), "ary[idx]");
 }
diff --git a/src/writer/msl/generator_impl_as_test.cc b/src/writer/msl/generator_impl_as_test.cc
index 35aab83..debc9f8 100644
--- a/src/writer/msl/generator_impl_as_test.cc
+++ b/src/writer/msl/generator_impl_as_test.cc
@@ -17,6 +17,7 @@
 #include "gtest/gtest.h"
 #include "src/ast/as_expression.h"
 #include "src/ast/identifier_expression.h"
+#include "src/ast/module.h"
 #include "src/ast/type/f32_type.h"
 #include "src/writer/msl/generator_impl.h"
 
@@ -32,7 +33,8 @@
   auto id = std::make_unique<ast::IdentifierExpression>("id");
   ast::AsExpression as(&f32, std::move(id));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitExpression(&as)) << g.error();
   EXPECT_EQ(g.result(), "as_type<float>(id)");
 }
diff --git a/src/writer/msl/generator_impl_assign_test.cc b/src/writer/msl/generator_impl_assign_test.cc
index 749ddf8..db1426b 100644
--- a/src/writer/msl/generator_impl_assign_test.cc
+++ b/src/writer/msl/generator_impl_assign_test.cc
@@ -18,6 +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/writer/msl/generator_impl.h"
 
 namespace tint {
@@ -32,7 +33,8 @@
   auto rhs = std::make_unique<ast::IdentifierExpression>("rhs");
   ast::AssignmentStatement assign(std::move(lhs), std::move(rhs));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitStatement(&assign)) << g.error();
diff --git a/src/writer/msl/generator_impl_binary_test.cc b/src/writer/msl/generator_impl_binary_test.cc
index 017e6ac..fb9329f 100644
--- a/src/writer/msl/generator_impl_binary_test.cc
+++ b/src/writer/msl/generator_impl_binary_test.cc
@@ -17,6 +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/writer/msl/generator_impl.h"
 
 namespace tint {
@@ -41,7 +42,8 @@
 
   ast::BinaryExpression expr(params.op, std::move(left), std::move(right));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitExpression(&expr)) << g.error();
   EXPECT_EQ(g.result(), params.result);
 }
diff --git a/src/writer/msl/generator_impl_break_test.cc b/src/writer/msl/generator_impl_break_test.cc
index 8f33da0..941faa8 100644
--- a/src/writer/msl/generator_impl_break_test.cc
+++ b/src/writer/msl/generator_impl_break_test.cc
@@ -17,6 +17,7 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/break_statement.h"
+#include "src/ast/module.h"
 #include "src/writer/msl/generator_impl.h"
 
 namespace tint {
@@ -29,7 +30,8 @@
 TEST_F(MslGeneratorImplTest, Emit_Break) {
   ast::BreakStatement b;
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitStatement(&b)) << g.error();
diff --git a/src/writer/msl/generator_impl_call_test.cc b/src/writer/msl/generator_impl_call_test.cc
index af4defe..97272c6 100644
--- a/src/writer/msl/generator_impl_call_test.cc
+++ b/src/writer/msl/generator_impl_call_test.cc
@@ -41,9 +41,7 @@
   ast::Module m;
   m.AddFunction(std::move(func));
 
-  GeneratorImpl g;
-  g.set_module_for_testing(&m);
-
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitExpression(&call)) << g.error();
   EXPECT_EQ(g.result(), "my_func()");
 }
@@ -63,9 +61,7 @@
   ast::Module m;
   m.AddFunction(std::move(func));
 
-  GeneratorImpl g;
-  g.set_module_for_testing(&m);
-
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitExpression(&call)) << g.error();
   EXPECT_EQ(g.result(), "my_func(param1, param2)");
 }
diff --git a/src/writer/msl/generator_impl_case_test.cc b/src/writer/msl/generator_impl_case_test.cc
index a53f207..9054873 100644
--- a/src/writer/msl/generator_impl_case_test.cc
+++ b/src/writer/msl/generator_impl_case_test.cc
@@ -19,6 +19,7 @@
 #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/ast/type/i32_type.h"
 #include "src/writer/msl/generator_impl.h"
@@ -40,7 +41,8 @@
   lit.push_back(std::make_unique<ast::SintLiteral>(&i32, 5));
   ast::CaseStatement c(std::move(lit), std::move(body));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitCase(&c)) << g.error();
@@ -59,7 +61,8 @@
   lit.push_back(std::make_unique<ast::SintLiteral>(&i32, 5));
   ast::CaseStatement c(std::move(lit), std::move(body));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitCase(&c)) << g.error();
@@ -79,7 +82,8 @@
   lit.push_back(std::make_unique<ast::SintLiteral>(&i32, 5));
   ast::CaseStatement c(std::move(lit), std::move(body));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitCase(&c)) << g.error();
@@ -100,7 +104,8 @@
   lit.push_back(std::make_unique<ast::SintLiteral>(&i32, 6));
   ast::CaseStatement c(std::move(lit), std::move(body));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitCase(&c)) << g.error();
@@ -119,7 +124,8 @@
 
   c.set_body(std::move(body));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitCase(&c)) << g.error();
diff --git a/src/writer/msl/generator_impl_cast_test.cc b/src/writer/msl/generator_impl_cast_test.cc
index 04dece4..f760335 100644
--- a/src/writer/msl/generator_impl_cast_test.cc
+++ b/src/writer/msl/generator_impl_cast_test.cc
@@ -17,6 +17,7 @@
 #include "gtest/gtest.h"
 #include "src/ast/cast_expression.h"
 #include "src/ast/identifier_expression.h"
+#include "src/ast/module.h"
 #include "src/ast/type/f32_type.h"
 #include "src/ast/type/vector_type.h"
 #include "src/writer/msl/generator_impl.h"
@@ -33,7 +34,8 @@
   auto id = std::make_unique<ast::IdentifierExpression>("id");
   ast::CastExpression cast(&f32, std::move(id));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitExpression(&cast)) << g.error();
   EXPECT_EQ(g.result(), "float(id)");
 }
@@ -45,7 +47,8 @@
   auto id = std::make_unique<ast::IdentifierExpression>("id");
   ast::CastExpression cast(&vec3, std::move(id));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitExpression(&cast)) << g.error();
   EXPECT_EQ(g.result(), "float3(id)");
 }
diff --git a/src/writer/msl/generator_impl_constructor_test.cc b/src/writer/msl/generator_impl_constructor_test.cc
index 281a1a0..8657fe3 100644
--- a/src/writer/msl/generator_impl_constructor_test.cc
+++ b/src/writer/msl/generator_impl_constructor_test.cc
@@ -15,6 +15,7 @@
 #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/array_type.h"
@@ -40,7 +41,8 @@
   auto lit = std::make_unique<ast::BoolLiteral>(&bool_type, false);
   ast::ScalarConstructorExpression expr(std::move(lit));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error();
   EXPECT_EQ(g.result(), "false");
 }
@@ -50,7 +52,8 @@
   auto lit = std::make_unique<ast::SintLiteral>(&i32, -12345);
   ast::ScalarConstructorExpression expr(std::move(lit));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error();
   EXPECT_EQ(g.result(), "-12345");
 }
@@ -60,7 +63,8 @@
   auto lit = std::make_unique<ast::UintLiteral>(&u32, 56779);
   ast::ScalarConstructorExpression expr(std::move(lit));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error();
   EXPECT_EQ(g.result(), "56779u");
 }
@@ -70,7 +74,8 @@
   auto lit = std::make_unique<ast::FloatLiteral>(&f32, 1.5e27);
   ast::ScalarConstructorExpression expr(std::move(lit));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error();
   EXPECT_EQ(g.result(), "1.49999995e+27f");
 }
@@ -85,7 +90,8 @@
 
   ast::TypeConstructorExpression expr(&f32, std::move(values));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error();
   EXPECT_EQ(g.result(), "float(-1.20000004e-05f)");
 }
@@ -100,7 +106,8 @@
 
   ast::TypeConstructorExpression expr(&b, std::move(values));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error();
   EXPECT_EQ(g.result(), "bool(true)");
 }
@@ -115,7 +122,8 @@
 
   ast::TypeConstructorExpression expr(&i32, std::move(values));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error();
   EXPECT_EQ(g.result(), "int(-12345)");
 }
@@ -130,7 +138,8 @@
 
   ast::TypeConstructorExpression expr(&u32, std::move(values));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error();
   EXPECT_EQ(g.result(), "uint(12345u)");
 }
@@ -152,7 +161,8 @@
 
   ast::TypeConstructorExpression expr(&vec, std::move(values));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error();
   EXPECT_EQ(g.result(), "float3(1.00000000f, 2.00000000f, 3.00000000f)");
 }
@@ -164,7 +174,8 @@
   ast::ExpressionList values;
   ast::TypeConstructorExpression expr(&vec, std::move(values));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error();
   EXPECT_EQ(g.result(), "float3(0.0f)");
 }
@@ -201,7 +212,8 @@
 
   ast::TypeConstructorExpression expr(&mat, std::move(mat_values));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error();
 
   // A matrix of type T with n columns and m rows can also be constructed from
@@ -241,7 +253,8 @@
 
   ast::TypeConstructorExpression expr(&ary, std::move(ary_values));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitConstructor(&expr)) << g.error();
   EXPECT_EQ(g.result(), std::string("{") +
                             "float3(1.00000000f, 2.00000000f, 3.00000000f), " +
diff --git a/src/writer/msl/generator_impl_continue_test.cc b/src/writer/msl/generator_impl_continue_test.cc
index 550c29f..389329a 100644
--- a/src/writer/msl/generator_impl_continue_test.cc
+++ b/src/writer/msl/generator_impl_continue_test.cc
@@ -17,6 +17,7 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/continue_statement.h"
+#include "src/ast/module.h"
 #include "src/writer/msl/generator_impl.h"
 
 namespace tint {
@@ -29,7 +30,8 @@
 TEST_F(MslGeneratorImplTest, Emit_Continue) {
   ast::ContinueStatement c;
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitStatement(&c)) << g.error();
diff --git a/src/writer/msl/generator_impl_entry_point_test.cc b/src/writer/msl/generator_impl_entry_point_test.cc
index a5bd1f3..ec237da 100644
--- a/src/writer/msl/generator_impl_entry_point_test.cc
+++ b/src/writer/msl/generator_impl_entry_point_test.cc
@@ -92,8 +92,7 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  GeneratorImpl g;
-  g.set_module_for_testing(&mod);
+  GeneratorImpl g(&mod);
   ASSERT_TRUE(g.EmitEntryPointData(ep_ptr)) << g.error();
   EXPECT_EQ(g.result(), R"(struct vtx_main_in {
   float foo [[attribute(0)]];
@@ -159,8 +158,7 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  GeneratorImpl g;
-  g.set_module_for_testing(&mod);
+  GeneratorImpl g(&mod);
   ASSERT_TRUE(g.EmitEntryPointData(ep_ptr)) << g.error();
   EXPECT_EQ(g.result(), R"(struct vtx_main_out {
   float foo [[user(locn0)]];
@@ -226,8 +224,7 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  GeneratorImpl g;
-  g.set_module_for_testing(&mod);
+  GeneratorImpl g(&mod);
   ASSERT_TRUE(g.EmitEntryPointData(ep_ptr)) << g.error();
   EXPECT_EQ(g.result(), R"(struct main_in {
   float foo [[user(locn0)]];
@@ -293,8 +290,7 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  GeneratorImpl g;
-  g.set_module_for_testing(&mod);
+  GeneratorImpl g(&mod);
   ASSERT_TRUE(g.EmitEntryPointData(ep_ptr)) << g.error();
   EXPECT_EQ(g.result(), R"(struct main_out {
   float foo [[color(0)]];
@@ -357,8 +353,7 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  GeneratorImpl g;
-  g.set_module_for_testing(&mod);
+  GeneratorImpl g(&mod);
   ASSERT_FALSE(g.EmitEntryPointData(ep_ptr)) << g.error();
   EXPECT_EQ(g.error(), R"(invalid location variable for pipeline stage)");
 }
@@ -416,8 +411,7 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  GeneratorImpl g;
-  g.set_module_for_testing(&mod);
+  GeneratorImpl g(&mod);
   ASSERT_FALSE(g.EmitEntryPointData(ep_ptr)) << g.error();
   EXPECT_EQ(g.error(), R"(invalid location variable for pipeline stage)");
 }
@@ -484,8 +478,7 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  GeneratorImpl g;
-  g.set_module_for_testing(&mod);
+  GeneratorImpl g(&mod);
   ASSERT_TRUE(g.EmitEntryPointData(ep_ptr)) << g.error();
   EXPECT_EQ(g.result(), R"(struct main_out {
   float depth [[depth(any)]];
diff --git a/src/writer/msl/generator_impl_function_test.cc b/src/writer/msl/generator_impl_function_test.cc
index 0558247..5a3e06e 100644
--- a/src/writer/msl/generator_impl_function_test.cc
+++ b/src/writer/msl/generator_impl_function_test.cc
@@ -60,10 +60,10 @@
   ast::Module m;
   m.AddFunction(std::move(func));
 
-  GeneratorImpl g;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
-  ASSERT_TRUE(g.Generate(m)) << g.error();
+  ASSERT_TRUE(g.Generate()) << g.error();
   EXPECT_EQ(g.result(), R"(#include <metal_stdlib>
 
   void my_func() {
@@ -86,10 +86,10 @@
   ast::Module m;
   m.AddFunction(std::move(func));
 
-  GeneratorImpl g;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
-  ASSERT_TRUE(g.Generate(m)) << g.error();
+  ASSERT_TRUE(g.Generate()) << g.error();
   EXPECT_EQ(g.result(), R"(#include <metal_stdlib>
 
   void main_tint_0() {
@@ -120,10 +120,10 @@
   ast::Module m;
   m.AddFunction(std::move(func));
 
-  GeneratorImpl g;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
-  ASSERT_TRUE(g.Generate(m)) << g.error();
+  ASSERT_TRUE(g.Generate()) << g.error();
   EXPECT_EQ(g.result(), R"(#include <metal_stdlib>
 
   void my_func(float a, int b) {
@@ -145,8 +145,8 @@
   m.AddFunction(std::move(func));
   m.AddEntryPoint(std::move(ep));
 
-  GeneratorImpl g;
-  ASSERT_TRUE(g.Generate(m)) << g.error();
+  GeneratorImpl g(&m);
+  ASSERT_TRUE(g.Generate()) << g.error();
   EXPECT_EQ(g.result(), R"(#include <metal_stdlib>
 
 fragment void frag_main() {
@@ -199,8 +199,8 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  GeneratorImpl g;
-  ASSERT_TRUE(g.Generate(mod)) << g.error();
+  GeneratorImpl g(&mod);
+  ASSERT_TRUE(g.Generate()) << g.error();
   EXPECT_EQ(g.result(), R"(#include <metal_stdlib>
 
 struct frag_main_in {
@@ -271,8 +271,8 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  GeneratorImpl g;
-  ASSERT_TRUE(g.Generate(mod)) << g.error();
+  GeneratorImpl g(&mod);
+  ASSERT_TRUE(g.Generate()) << g.error();
   EXPECT_EQ(g.result(), R"(#include <metal_stdlib>
 
 struct frag_main_out {
@@ -332,8 +332,8 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  GeneratorImpl g;
-  ASSERT_TRUE(g.Generate(mod)) << g.error();
+  GeneratorImpl g(&mod);
+  ASSERT_TRUE(g.Generate()) << g.error();
   EXPECT_EQ(g.result(), R"(#include <metal_stdlib>
 
 fragment void frag_main(constant float4& coord [[buffer(0)]]) {
@@ -418,8 +418,8 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  GeneratorImpl g;
-  ASSERT_TRUE(g.Generate(mod)) << g.error();
+  GeneratorImpl g(&mod);
+  ASSERT_TRUE(g.Generate()) << g.error();
   EXPECT_EQ(g.result(), R"(#include <metal_stdlib>
 
 struct ep_1_in {
@@ -517,8 +517,8 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  GeneratorImpl g;
-  ASSERT_TRUE(g.Generate(mod)) << g.error();
+  GeneratorImpl g(&mod);
+  ASSERT_TRUE(g.Generate()) << g.error();
   EXPECT_EQ(g.result(), R"(#include <metal_stdlib>
 
 struct ep_1_out {
@@ -600,8 +600,8 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  GeneratorImpl g;
-  ASSERT_TRUE(g.Generate(mod)) << g.error();
+  GeneratorImpl g(&mod);
+  ASSERT_TRUE(g.Generate()) << g.error();
   EXPECT_EQ(g.result(), R"(#include <metal_stdlib>
 
 float sub_func(constant float4& coord, float param) {
@@ -677,8 +677,8 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  GeneratorImpl g;
-  ASSERT_TRUE(g.Generate(mod)) << g.error();
+  GeneratorImpl g(&mod);
+  ASSERT_TRUE(g.Generate()) << g.error();
   EXPECT_EQ(g.result(), R"(#include <metal_stdlib>
 
 struct ep_1_in {
@@ -772,8 +772,8 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  GeneratorImpl g;
-  ASSERT_TRUE(g.Generate(mod)) << g.error();
+  GeneratorImpl g(&mod);
+  ASSERT_TRUE(g.Generate()) << g.error();
   EXPECT_EQ(g.result(), R"(#include <metal_stdlib>
 
 struct ep_1_out {
@@ -838,8 +838,8 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  GeneratorImpl g;
-  ASSERT_TRUE(g.Generate(mod)) << g.error();
+  GeneratorImpl g(&mod);
+  ASSERT_TRUE(g.Generate()) << g.error();
   EXPECT_EQ(g.result(), R"(#include <metal_stdlib>
 
 float sub_func() {
@@ -870,8 +870,8 @@
   m.AddFunction(std::move(func));
   m.AddEntryPoint(std::move(ep));
 
-  GeneratorImpl g;
-  ASSERT_TRUE(g.Generate(m)) << g.error();
+  GeneratorImpl g(&m);
+  ASSERT_TRUE(g.Generate()) << g.error();
   EXPECT_EQ(g.result(), R"(#include <metal_stdlib>
 
 kernel void my_main() {
@@ -892,8 +892,8 @@
   m.AddFunction(std::move(func));
   m.AddEntryPoint(std::move(ep));
 
-  GeneratorImpl g;
-  ASSERT_TRUE(g.Generate(m)) << g.error();
+  GeneratorImpl g(&m);
+  ASSERT_TRUE(g.Generate()) << g.error();
   EXPECT_EQ(g.result(), R"(#include <metal_stdlib>
 
 kernel void main_tint_0() {
@@ -921,10 +921,10 @@
   ast::Module m;
   m.AddFunction(std::move(func));
 
-  GeneratorImpl g;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
-  ASSERT_TRUE(g.Generate(m)) << g.error();
+  ASSERT_TRUE(g.Generate()) << g.error();
   EXPECT_EQ(g.result(), R"(#include <metal_stdlib>
 
   void my_func(float a[5]) {
diff --git a/src/writer/msl/generator_impl_identifier_test.cc b/src/writer/msl/generator_impl_identifier_test.cc
index f137b56..7c7bc19 100644
--- a/src/writer/msl/generator_impl_identifier_test.cc
+++ b/src/writer/msl/generator_impl_identifier_test.cc
@@ -14,6 +14,7 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/identifier_expression.h"
+#include "src/ast/module.h"
 #include "src/writer/msl/generator_impl.h"
 
 namespace tint {
@@ -26,7 +27,8 @@
 TEST_F(MslGeneratorImplTest, DISABLED_EmitExpression_Identifier) {
   ast::IdentifierExpression i(std::vector<std::string>{"std", "glsl"});
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitExpression(&i)) << g.error();
   EXPECT_EQ(g.result(), "std::glsl");
 }
@@ -34,7 +36,8 @@
 TEST_F(MslGeneratorImplTest, EmitIdentifierExpression_Single) {
   ast::IdentifierExpression i("foo");
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitExpression(&i)) << g.error();
   EXPECT_EQ(g.result(), "foo");
 }
@@ -42,7 +45,8 @@
 TEST_F(MslGeneratorImplTest, EmitIdentifierExpression_Single_WithCollision) {
   ast::IdentifierExpression i("virtual");
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitExpression(&i)) << g.error();
   EXPECT_EQ(g.result(), "virtual_tint_0");
 }
@@ -51,7 +55,8 @@
 TEST_F(MslGeneratorImplTest, DISABLED_EmitIdentifierExpression_MultipleNames) {
   ast::IdentifierExpression i({"std", "glsl", "init"});
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitExpression(&i)) << g.error();
   EXPECT_EQ(g.result(), "std::glsl::init");
 }
diff --git a/src/writer/msl/generator_impl_if_test.cc b/src/writer/msl/generator_impl_if_test.cc
index b7a78b7..e2c2755 100644
--- a/src/writer/msl/generator_impl_if_test.cc
+++ b/src/writer/msl/generator_impl_if_test.cc
@@ -16,6 +16,7 @@
 #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/writer/msl/generator_impl.h"
 
@@ -33,7 +34,8 @@
 
   ast::IfStatement i(std::move(cond), std::move(body));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitStatement(&i)) << g.error();
@@ -60,7 +62,8 @@
   ast::IfStatement i(std::move(cond), std::move(body));
   i.set_else_statements(std::move(elses));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitStatement(&i)) << g.error();
@@ -86,7 +89,8 @@
   ast::IfStatement i(std::move(cond), std::move(body));
   i.set_else_statements(std::move(elses));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitStatement(&i)) << g.error();
@@ -119,7 +123,8 @@
   ast::IfStatement i(std::move(cond), std::move(body));
   i.set_else_statements(std::move(elses));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitStatement(&i)) << g.error();
diff --git a/src/writer/msl/generator_impl_kill_test.cc b/src/writer/msl/generator_impl_kill_test.cc
index 7eb7f02..9445d95 100644
--- a/src/writer/msl/generator_impl_kill_test.cc
+++ b/src/writer/msl/generator_impl_kill_test.cc
@@ -14,6 +14,7 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/kill_statement.h"
+#include "src/ast/module.h"
 #include "src/writer/msl/generator_impl.h"
 
 namespace tint {
@@ -26,7 +27,8 @@
 TEST_F(MslGeneratorImplTest, Emit_Kill) {
   ast::KillStatement k;
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitStatement(&k)) << g.error();
diff --git a/src/writer/msl/generator_impl_loop_test.cc b/src/writer/msl/generator_impl_loop_test.cc
index cbbbfb1..8fa015c 100644
--- a/src/writer/msl/generator_impl_loop_test.cc
+++ b/src/writer/msl/generator_impl_loop_test.cc
@@ -20,6 +20,7 @@
 #include "src/ast/identifier_expression.h"
 #include "src/ast/kill_statement.h"
 #include "src/ast/loop_statement.h"
+#include "src/ast/module.h"
 #include "src/ast/return_statement.h"
 #include "src/ast/type/f32_type.h"
 #include "src/ast/variable.h"
@@ -39,7 +40,8 @@
 
   ast::LoopStatement l(std::move(body), {});
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitStatement(&l)) << g.error();
@@ -58,7 +60,8 @@
 
   ast::LoopStatement l(std::move(body), std::move(continuing));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitStatement(&l)) << g.error();
@@ -97,7 +100,8 @@
 
   ast::LoopStatement outer(std::move(body), std::move(continuing));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitStatement(&outer)) << g.error();
@@ -148,7 +152,8 @@
 
   ast::LoopStatement outer(std::move(body), std::move(continuing));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitStatement(&outer)) << g.error();
diff --git a/src/writer/msl/generator_impl_member_accessor_test.cc b/src/writer/msl/generator_impl_member_accessor_test.cc
index a21e81b..9567511 100644
--- a/src/writer/msl/generator_impl_member_accessor_test.cc
+++ b/src/writer/msl/generator_impl_member_accessor_test.cc
@@ -17,6 +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/writer/msl/generator_impl.h"
 
 namespace tint {
@@ -32,7 +33,8 @@
 
   ast::MemberAccessorExpression expr(std::move(str), std::move(mem));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitExpression(&expr)) << g.error();
   EXPECT_EQ(g.result(), "str.mem");
 }
diff --git a/src/writer/msl/generator_impl_module_constant_test.cc b/src/writer/msl/generator_impl_module_constant_test.cc
index 7f38a34..875f279 100644
--- a/src/writer/msl/generator_impl_module_constant_test.cc
+++ b/src/writer/msl/generator_impl_module_constant_test.cc
@@ -17,6 +17,7 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/float_literal.h"
+#include "src/ast/module.h"
 #include "src/ast/scalar_constructor_expression.h"
 #include "src/ast/type/array_type.h"
 #include "src/ast/type/f32_type.h"
@@ -49,7 +50,8 @@
   var->set_constructor(
       std::make_unique<ast::TypeConstructorExpression>(&ary, std::move(exprs)));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitProgramConstVariable(var.get())) << g.error();
   EXPECT_EQ(
       g.result(),
diff --git a/src/writer/msl/generator_impl_return_test.cc b/src/writer/msl/generator_impl_return_test.cc
index 50111ae..3d68fa2 100644
--- a/src/writer/msl/generator_impl_return_test.cc
+++ b/src/writer/msl/generator_impl_return_test.cc
@@ -17,6 +17,7 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/identifier_expression.h"
+#include "src/ast/module.h"
 #include "src/ast/return_statement.h"
 #include "src/writer/msl/generator_impl.h"
 
@@ -30,7 +31,8 @@
 TEST_F(MslGeneratorImplTest, Emit_Return) {
   ast::ReturnStatement r;
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitStatement(&r)) << g.error();
@@ -41,7 +43,8 @@
   auto expr = std::make_unique<ast::IdentifierExpression>("expr");
   ast::ReturnStatement r(std::move(expr));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitStatement(&r)) << g.error();
diff --git a/src/writer/msl/generator_impl_switch_test.cc b/src/writer/msl/generator_impl_switch_test.cc
index 56a919d..caffd1d 100644
--- a/src/writer/msl/generator_impl_switch_test.cc
+++ b/src/writer/msl/generator_impl_switch_test.cc
@@ -18,6 +18,7 @@
 #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/ast/type/i32_type.h"
@@ -53,7 +54,8 @@
   auto cond = std::make_unique<ast::IdentifierExpression>("cond");
   ast::SwitchStatement s(std::move(cond), std::move(body));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitStatement(&s)) << g.error();
diff --git a/src/writer/msl/generator_impl_test.cc b/src/writer/msl/generator_impl_test.cc
index 6763757..575264c 100644
--- a/src/writer/msl/generator_impl_test.cc
+++ b/src/writer/msl/generator_impl_test.cc
@@ -53,9 +53,9 @@
   m.AddEntryPoint(std::make_unique<ast::EntryPoint>(
       ast::PipelineStage::kCompute, "my_func", ""));
 
-  GeneratorImpl g;
+  GeneratorImpl g(&m);
 
-  ASSERT_TRUE(g.Generate(m)) << g.error();
+  ASSERT_TRUE(g.Generate()) << g.error();
   EXPECT_EQ(g.result(), R"(#import <metal_lib>
 
 compute void my_func() {
@@ -64,12 +64,14 @@
 }
 
 TEST_F(MslGeneratorImplTest, InputStructName) {
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_EQ(g.generate_name("func_main_in"), "func_main_in");
 }
 
 TEST_F(MslGeneratorImplTest, InputStructName_ConflictWithExisting) {
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
 
   // Register the struct name as existing.
   auto* namer = g.namer_for_testing();
@@ -79,7 +81,8 @@
 }
 
 TEST_F(MslGeneratorImplTest, NameConflictWith_InputStructName) {
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_EQ(g.generate_name("func_main_in"), "func_main_in");
 
   ast::IdentifierExpression ident("func_main_in");
@@ -99,7 +102,8 @@
 TEST_P(MslBuiltinConversionTest, Emit) {
   auto params = GetParam();
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   EXPECT_EQ(g.builtin_to_attribute(params.builtin),
             std::string(params.attribute_name));
 }
@@ -124,46 +128,53 @@
 TEST_F(MslGeneratorImplTest, calculate_alignment_size_alias) {
   ast::type::F32Type f32;
   ast::type::AliasType alias("a", &f32);
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   EXPECT_EQ(4u, g.calculate_alignment_size(&alias));
 }
 
 TEST_F(MslGeneratorImplTest, calculate_alignment_size_array) {
   ast::type::F32Type f32;
   ast::type::ArrayType ary(&f32, 4);
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   EXPECT_EQ(4u * 4u, g.calculate_alignment_size(&ary));
 }
 
 TEST_F(MslGeneratorImplTest, calculate_alignment_size_bool) {
   ast::type::BoolType bool_type;
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   EXPECT_EQ(1u, g.calculate_alignment_size(&bool_type));
 }
 
 TEST_F(MslGeneratorImplTest, calculate_alignment_size_f32) {
   ast::type::F32Type f32;
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   EXPECT_EQ(4u, g.calculate_alignment_size(&f32));
 }
 
 TEST_F(MslGeneratorImplTest, calculate_alignment_size_i32) {
   ast::type::I32Type i32;
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   EXPECT_EQ(4u, g.calculate_alignment_size(&i32));
 }
 
 TEST_F(MslGeneratorImplTest, calculate_alignment_size_matrix) {
   ast::type::F32Type f32;
   ast::type::MatrixType mat(&f32, 3, 2);
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   EXPECT_EQ(4u * 3u * 2u, g.calculate_alignment_size(&mat));
 }
 
 TEST_F(MslGeneratorImplTest, calculate_alignment_size_pointer) {
   ast::type::BoolType bool_type;
   ast::type::PointerType ptr(&bool_type, ast::StorageClass::kPrivate);
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   EXPECT_EQ(0u, g.calculate_alignment_size(&ptr));
 }
 
@@ -191,7 +202,8 @@
 
   ast::type::StructType s(std::move(str));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   EXPECT_EQ(132u, g.calculate_alignment_size(&s));
 }
 
@@ -237,13 +249,15 @@
 
   ast::type::StructType outer_s(std::move(outer_str));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   EXPECT_EQ(80u, g.calculate_alignment_size(&outer_s));
 }
 
 TEST_F(MslGeneratorImplTest, calculate_alignment_size_u32) {
   ast::type::U32Type u32;
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   EXPECT_EQ(4u, g.calculate_alignment_size(&u32));
 }
 
@@ -261,7 +275,8 @@
 
   ast::type::BoolType bool_type;
   ast::type::VectorType vec(&bool_type, param.elements);
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   EXPECT_EQ(param.byte_size, g.calculate_alignment_size(&vec));
 }
 INSTANTIATE_TEST_SUITE_P(MslGeneratorImplTest,
@@ -276,7 +291,8 @@
 
   ast::type::I32Type i32;
   ast::type::VectorType vec(&i32, param.elements);
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   EXPECT_EQ(param.byte_size, g.calculate_alignment_size(&vec));
 }
 INSTANTIATE_TEST_SUITE_P(MslGeneratorImplTest,
@@ -291,7 +307,8 @@
 
   ast::type::U32Type u32;
   ast::type::VectorType vec(&u32, param.elements);
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   EXPECT_EQ(param.byte_size, g.calculate_alignment_size(&vec));
 }
 INSTANTIATE_TEST_SUITE_P(MslGeneratorImplTest,
@@ -306,7 +323,8 @@
 
   ast::type::F32Type f32;
   ast::type::VectorType vec(&f32, param.elements);
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   EXPECT_EQ(param.byte_size, g.calculate_alignment_size(&vec));
 }
 INSTANTIATE_TEST_SUITE_P(MslGeneratorImplTest,
diff --git a/src/writer/msl/generator_impl_type_test.cc b/src/writer/msl/generator_impl_type_test.cc
index db29cfb..6d4f8d1 100644
--- a/src/writer/msl/generator_impl_type_test.cc
+++ b/src/writer/msl/generator_impl_type_test.cc
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 #include "gtest/gtest.h"
+#include "src/ast/module.h"
 #include "src/ast/struct.h"
 #include "src/ast/struct_decoration.h"
 #include "src/ast/struct_member.h"
@@ -41,7 +42,8 @@
   ast::type::F32Type f32;
   ast::type::AliasType alias("alias", &f32);
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitType(&alias, "")) << g.error();
   EXPECT_EQ(g.result(), "alias");
 }
@@ -50,7 +52,8 @@
   ast::type::F32Type f32;
   ast::type::AliasType alias("bool", &f32);
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitType(&alias, "")) << g.error();
   EXPECT_EQ(g.result(), "bool_tint_0");
 }
@@ -59,7 +62,8 @@
   ast::type::BoolType b;
   ast::type::ArrayType a(&b, 4);
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitType(&a, "ary")) << g.error();
   EXPECT_EQ(g.result(), "bool ary[4]");
 }
@@ -69,7 +73,8 @@
   ast::type::ArrayType a(&b, 4);
   ast::type::ArrayType c(&a, 5);
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitType(&c, "ary")) << g.error();
   EXPECT_EQ(g.result(), "bool ary[5][4]");
 }
@@ -81,7 +86,8 @@
   ast::type::ArrayType c(&a, 5);
   ast::type::ArrayType d(&c);
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitType(&c, "ary")) << g.error();
   EXPECT_EQ(g.result(), "bool ary[5][4][1]");
 }
@@ -92,7 +98,8 @@
   ast::type::ArrayType c(&a, 5);
   ast::type::ArrayType d(&c, 6);
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitType(&d, "ary")) << g.error();
   EXPECT_EQ(g.result(), "bool ary[6][5][4]");
 }
@@ -101,7 +108,8 @@
   ast::type::BoolType b;
   ast::type::ArrayType a(&b, 4);
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitType(&a, "bool")) << g.error();
   EXPECT_EQ(g.result(), "bool bool_tint_0[4]");
 }
@@ -110,7 +118,8 @@
   ast::type::BoolType b;
   ast::type::ArrayType a(&b, 4);
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitType(&a, "")) << g.error();
   EXPECT_EQ(g.result(), "bool[4]");
 }
@@ -119,7 +128,8 @@
   ast::type::BoolType b;
   ast::type::ArrayType a(&b);
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitType(&a, "ary")) << g.error();
   EXPECT_EQ(g.result(), "bool ary[1]");
 }
@@ -128,7 +138,8 @@
   ast::type::BoolType b;
   ast::type::ArrayType a(&b);
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitType(&a, "discard_fragment")) << g.error();
   EXPECT_EQ(g.result(), "bool discard_fragment_tint_0[1]");
 }
@@ -136,7 +147,8 @@
 TEST_F(MslGeneratorImplTest, EmitType_Bool) {
   ast::type::BoolType b;
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitType(&b, "")) << g.error();
   EXPECT_EQ(g.result(), "bool");
 }
@@ -144,7 +156,8 @@
 TEST_F(MslGeneratorImplTest, EmitType_F32) {
   ast::type::F32Type f32;
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitType(&f32, "")) << g.error();
   EXPECT_EQ(g.result(), "float");
 }
@@ -152,7 +165,8 @@
 TEST_F(MslGeneratorImplTest, EmitType_I32) {
   ast::type::I32Type i32;
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitType(&i32, "")) << g.error();
   EXPECT_EQ(g.result(), "int");
 }
@@ -161,7 +175,8 @@
   ast::type::F32Type f32;
   ast::type::MatrixType m(&f32, 3, 2);
 
-  GeneratorImpl g;
+  ast::Module mod;
+  GeneratorImpl g(&mod);
   ASSERT_TRUE(g.EmitType(&m, "")) << g.error();
   EXPECT_EQ(g.result(), "float2x3");
 }
@@ -171,7 +186,8 @@
   ast::type::F32Type f32;
   ast::type::PointerType p(&f32, ast::StorageClass::kWorkgroup);
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitType(&p, "")) << g.error();
   EXPECT_EQ(g.result(), "float*");
 }
@@ -194,7 +210,8 @@
 
   ast::type::StructType s(std::move(str));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitType(&s, "")) << g.error();
   EXPECT_EQ(g.result(), R"(struct {
   int a;
@@ -226,7 +243,8 @@
 
   ast::type::StructType s(std::move(str));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitType(&s, "")) << g.error();
   EXPECT_EQ(g.result(), R"(struct {
   int8_t pad_0[4];
@@ -255,7 +273,8 @@
 
   ast::type::StructType s(std::move(str));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitType(&s, "")) << g.error();
   EXPECT_EQ(g.result(), R"(struct {
   int main_tint_0;
@@ -283,7 +302,8 @@
 
   ast::type::StructType s(std::move(str));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitType(&s, "")) << g.error();
   EXPECT_EQ(g.result(), R"(struct {
   int a;
@@ -294,7 +314,8 @@
 TEST_F(MslGeneratorImplTest, EmitType_U32) {
   ast::type::U32Type u32;
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitType(&u32, "")) << g.error();
   EXPECT_EQ(g.result(), "uint");
 }
@@ -303,7 +324,8 @@
   ast::type::F32Type f32;
   ast::type::VectorType v(&f32, 3);
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitType(&v, "")) << g.error();
   EXPECT_EQ(g.result(), "float3");
 }
@@ -311,7 +333,8 @@
 TEST_F(MslGeneratorImplTest, EmitType_Void) {
   ast::type::VoidType v;
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitType(&v, "")) << g.error();
   EXPECT_EQ(g.result(), "void");
 }
diff --git a/src/writer/msl/generator_impl_unary_op_test.cc b/src/writer/msl/generator_impl_unary_op_test.cc
index 6a01597..46e9f26 100644
--- a/src/writer/msl/generator_impl_unary_op_test.cc
+++ b/src/writer/msl/generator_impl_unary_op_test.cc
@@ -17,6 +17,7 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/identifier_expression.h"
+#include "src/ast/module.h"
 #include "src/ast/unary_op_expression.h"
 #include "src/writer/msl/generator_impl.h"
 
@@ -40,7 +41,8 @@
   auto expr = std::make_unique<ast::IdentifierExpression>("expr");
   ast::UnaryOpExpression op(params.op, std::move(expr));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitExpression(&op)) << g.error();
   EXPECT_EQ(g.result(), std::string(params.name) + "(expr)");
 }
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 1f99714..043ef7a 100644
--- a/src/writer/msl/generator_impl_variable_decl_statement_test.cc
+++ b/src/writer/msl/generator_impl_variable_decl_statement_test.cc
@@ -17,6 +17,7 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/identifier_expression.h"
+#include "src/ast/module.h"
 #include "src/ast/type/array_type.h"
 #include "src/ast/type/f32_type.h"
 #include "src/ast/type/vector_type.h"
@@ -38,7 +39,8 @@
 
   ast::VariableDeclStatement stmt(std::move(var));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitStatement(&stmt)) << g.error();
@@ -54,7 +56,8 @@
 
   ast::VariableDeclStatement stmt(std::move(var));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitStatement(&stmt)) << g.error();
@@ -68,7 +71,8 @@
 
   ast::VariableDeclStatement stmt(std::move(var));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitStatement(&stmt)) << g.error();
@@ -82,7 +86,8 @@
 
   ast::VariableDeclStatement stmt(std::move(var));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   g.increment_indent();
 
   ASSERT_TRUE(g.EmitStatement(&stmt)) << g.error();
@@ -99,7 +104,8 @@
 
   ast::VariableDeclStatement stmt(std::move(var));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitStatement(&stmt)) << g.error();
   EXPECT_EQ(g.result(), R"(float a = initializer;
 )");
@@ -119,7 +125,8 @@
 
   ast::VariableDeclStatement stmt(std::move(var));
 
-  GeneratorImpl g;
+  ast::Module m;
+  GeneratorImpl g(&m);
   ASSERT_TRUE(g.EmitStatement(&stmt)) << g.error();
   EXPECT_EQ(g.result(), R"(float3 a = float3(0.0f);
 )");