Import Tint changes from Dawn

Changes:
  - ed70ac0399fc13caf9cc63b9e3d1c0e975c37b51 [ir][msl] Emit basic constants types by dan sinclair <dsinclair@chromium.org>
  - 965321b6b9867d73838acecca06a4122ae32dfbe [ir][msl] Emit struct types by dan sinclair <dsinclair@chromium.org>
  - 18e01a2d5ba9bbaee98a0f07fe6c951b5f2dca68 [ir][msl] Emit sampler and texture types by dan sinclair <dsinclair@chromium.org>
  - 0839656eb98d798021800153dae86ff962370c91 [ir][msl] Emit pointer types by dan sinclair <dsinclair@chromium.org>
  - d1a27c43cbd9cffc288cdc07abf6151984c4090e [msl] Simplify `EmitType` in MSL Generator. by dan sinclair <dsinclair@chromium.org>
  - a71b785f4b8f479f2527ee896f809ffab799d6e0 [ir][msl] Emit atomic types by dan sinclair <dsinclair@chromium.org>
  - 9f44ac94fbfb5e46da7d38757f982f6fde8abf8b [ir][msl] Emit vector and matrix types by dan sinclair <dsinclair@chromium.org>
  - 83f233632ad465c159cad9cfc1cfbd6aa1ee022f [ir][msl] Emit array types by dan sinclair <dsinclair@chromium.org>
  - 67a1893b6a12ed2c6f8c057bc7f2de0a11672972 [writer] Update generators to use CamelCase by dan sinclair <dsinclair@chromium.org>
  - 1bddaed0699d5866fe07f811dc7a0813e7ab3541 [tint][fuzzers] Run SubstituteOverrides for tint_concurre... by Ben Clayton <bclayton@google.com>
  - fef48f1c1f3571a416be1e9e8393a864ce1c04f1 clang-format the codebase by Ben Clayton <bclayton@google.com>
  - 4c54cfcb21059d4ef76648d84831c04d5e09f763 [ir][spirv-writer] Emit constant structs by James Price <jrprice@google.com>
  - 9d8229bc4f617bb1fc11bbf6e93adff6653574ca [ir][msl] Add basic type emission by dan sinclair <dsinclair@chromium.org>
  - cadd0c0eec3f4e6214f698c314f5ad14ab731f63 [ir][msl] Stub out IR MSL Generator by dan sinclair <dsinclair@chromium.org>
GitOrigin-RevId: ed70ac0399fc13caf9cc63b9e3d1c0e975c37b51
Change-Id: Iaafda1bf0404bd715005d6848e5b65486634da0d
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/139160
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn
index 3901d5d..83d7421 100644
--- a/src/tint/BUILD.gn
+++ b/src/tint/BUILD.gn
@@ -1020,6 +1020,15 @@
     ":libtint_type_src",
     ":libtint_utils_src",
   ]
+
+  if (tint_build_ir) {
+    sources += [
+      "writer/ir_text_generator.cc",
+      "writer/ir_text_generator.h",
+    ]
+
+    deps += [ ":libtint_ir_src" ]
+  }
 }
 
 libtint_source_set("libtint_spv_writer_src") {
@@ -1121,6 +1130,8 @@
     "writer/msl/generator.h",
     "writer/msl/generator_impl.cc",
     "writer/msl/generator_impl.h",
+    "writer/msl/generator_support.cc",
+    "writer/msl/generator_support.h",
   ]
 
   deps = [
@@ -1136,6 +1147,18 @@
     ":libtint_utils_src",
     ":libtint_writer_src",
   ]
+
+  if (tint_build_ir) {
+    sources += [
+      "writer/msl/ir/generator_impl_ir.cc",
+      "writer/msl/ir/generator_impl_ir.h",
+    ]
+    deps += [
+      ":libtint_ir_builder_src",
+      ":libtint_ir_src",
+      ":libtint_ir_transform_src",
+    ]
+  }
 }
 
 libtint_source_set("libtint_hlsl_writer_src") {
@@ -2183,6 +2206,7 @@
       "writer/msl/generator_impl_type_test.cc",
       "writer/msl/generator_impl_unary_op_test.cc",
       "writer/msl/generator_impl_variable_decl_statement_test.cc",
+      "writer/msl/generator_support_test.cc",
       "writer/msl/test_helper.h",
     ]
 
@@ -2191,6 +2215,16 @@
       ":libtint_utils_src",
       ":tint_unittests_ast_src",
     ]
+
+    if (tint_build_ir) {
+      sources += [
+        "writer/msl/ir/generator_impl_ir_constant_test.cc",
+        "writer/msl/ir/generator_impl_ir_function_test.cc",
+        "writer/msl/ir/generator_impl_ir_type_test.cc",
+        "writer/msl/ir/test_helper_ir.h",
+      ]
+      deps += [ ":libtint_ir_src" ]
+    }
   }
 
   tint_unittests_source_set("tint_unittests_hlsl_writer_src") {
@@ -2374,6 +2408,7 @@
       ]
 
       deps = [
+        ":libtint_builtins_src",
         ":libtint_ir_builder_src",
         ":libtint_ir_src",
       ]
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt
index a9c5a8d..0ddae38 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -575,6 +575,8 @@
   writer/flatten_bindings.h
   writer/float_to_string.cc
   writer/float_to_string.h
+  writer/ir_text_generator.cc
+  writer/ir_text_generator.h
   writer/text_generator.cc
   writer/text_generator.h
   writer/text.cc
@@ -692,7 +694,16 @@
     writer/msl/generator.h
     writer/msl/generator_impl.cc
     writer/msl/generator_impl.h
+    writer/msl/generator_support.cc
+    writer/msl/generator_support.h
   )
+
+  if(${TINT_BUILD_IR})
+    list(APPEND TINT_LIB_SRCS
+      writer/msl/ir/generator_impl_ir.cc
+      writer/msl/ir/generator_impl_ir.h
+    )
+  endif()
 endif()
 
 if(${TINT_BUILD_GLSL_WRITER})
@@ -1440,8 +1451,18 @@
       writer/msl/generator_impl_type_test.cc
       writer/msl/generator_impl_unary_op_test.cc
       writer/msl/generator_impl_variable_decl_statement_test.cc
+      writer/msl/generator_support_test.cc
       writer/msl/test_helper.h
     )
+
+    if(${TINT_BUILD_IR})
+      list(APPEND TINT_TEST_SRCS
+        writer/msl/ir/generator_impl_ir_constant_test.cc
+        writer/msl/ir/generator_impl_ir_function_test.cc
+        writer/msl/ir/generator_impl_ir_type_test.cc
+        writer/msl/ir/test_helper_ir.h
+      )
+    endif()
   endif()
 
   if (${TINT_BUILD_GLSL_WRITER})
diff --git a/src/tint/fuzzers/BUILD.gn b/src/tint/fuzzers/BUILD.gn
index 5c896df..704f681 100644
--- a/src/tint/fuzzers/BUILD.gn
+++ b/src/tint/fuzzers/BUILD.gn
@@ -69,6 +69,8 @@
     ]
 
     sources = [
+      "apply_substitute_overrides.cc",
+      "apply_substitute_overrides.h",
       "data_builder.h",
       "mersenne_twister_engine.cc",
       "mersenne_twister_engine.h",
diff --git a/src/tint/fuzzers/CMakeLists.txt b/src/tint/fuzzers/CMakeLists.txt
index 7be1237..5640f95 100644
--- a/src/tint/fuzzers/CMakeLists.txt
+++ b/src/tint/fuzzers/CMakeLists.txt
@@ -15,6 +15,8 @@
 function(add_tint_fuzzer NAME)
   add_executable(${NAME}
     ${NAME}.cc
+    apply_substitute_overrides.cc
+    apply_substitute_overrides.h
     cli.cc
     cli.h
     data_builder.h
@@ -32,7 +34,7 @@
     tint_common_fuzzer.h
     tint_reader_writer_fuzzer.h
     transform_builder.h
-    )
+  )
   target_link_libraries(${NAME} libtint-fuzz)
   tint_default_compile_options(${NAME})
   target_compile_options(${NAME} PRIVATE -Wno-missing-prototypes)
@@ -100,6 +102,8 @@
     AND ${TINT_BUILD_SPV_WRITER}
     AND ${TINT_BUILD_WGSL_WRITER})
   add_executable(tint_black_box_fuzz_target
+    apply_substitute_overrides.cc
+    apply_substitute_overrides.h
     mersenne_twister_engine.cc
     mersenne_twister_engine.h
     random_generator.cc
@@ -109,7 +113,7 @@
     tint_black_box_fuzz_target.cc
     tint_common_fuzzer.cc
     tint_common_fuzzer.h
-    )
+  )
   target_link_libraries(tint_black_box_fuzz_target libtint)
   tint_default_compile_options(tint_black_box_fuzz_target)
 endif()
diff --git a/src/tint/fuzzers/apply_substitute_overrides.cc b/src/tint/fuzzers/apply_substitute_overrides.cc
new file mode 100644
index 0000000..324ca97
--- /dev/null
+++ b/src/tint/fuzzers/apply_substitute_overrides.cc
@@ -0,0 +1,48 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/fuzzers/apply_substitute_overrides.h"
+
+#include <memory>
+#include <utility>
+
+namespace tint::fuzzers {
+
+Program ApplySubstituteOverrides(Program&& program) {
+    ast::transform::SubstituteOverride::Config cfg;
+    inspector::Inspector inspector(&program);
+    auto default_values = inspector.GetOverrideDefaultValues();
+    for (const auto& [override_id, scalar] : default_values) {
+        // If the override is not null, then it has a default value, we can just let it use the
+        // provided default instead of overriding.
+        if (scalar.IsNull()) {
+            cfg.map.insert({override_id, 0.0});
+        }
+    }
+
+    if (default_values.empty()) {
+        return std::move(program);
+    }
+
+    transform::DataMap override_data;
+    override_data.Add<ast::transform::SubstituteOverride::Config>(cfg);
+
+    transform::Manager mgr;
+    mgr.append(std::make_unique<ast::transform::SubstituteOverride>());
+
+    transform::DataMap outputs;
+    return mgr.Run(&program, override_data, outputs);
+}
+
+}  // namespace tint::fuzzers
diff --git a/src/tint/fuzzers/apply_substitute_overrides.h b/src/tint/fuzzers/apply_substitute_overrides.h
new file mode 100644
index 0000000..76fb029
--- /dev/null
+++ b/src/tint/fuzzers/apply_substitute_overrides.h
@@ -0,0 +1,28 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_FUZZERS_APPLY_SUBSTITUTE_OVERRIDES_H_
+#define SRC_TINT_FUZZERS_APPLY_SUBSTITUTE_OVERRIDES_H_
+
+#include "tint/tint.h"
+
+namespace tint::fuzzers {
+
+/// @returns a new program with all overrides subsituted with const variables
+/// @param program the input program
+Program ApplySubstituteOverrides(Program&& program);
+
+}  // namespace tint::fuzzers
+
+#endif  // SRC_TINT_FUZZERS_APPLY_SUBSTITUTE_OVERRIDES_H_
diff --git a/src/tint/fuzzers/tint_ast_fuzzer/CMakeLists.txt b/src/tint/fuzzers/tint_ast_fuzzer/CMakeLists.txt
index 0d1f5a2..e311c82 100644
--- a/src/tint/fuzzers/tint_ast_fuzzer/CMakeLists.txt
+++ b/src/tint/fuzzers/tint_ast_fuzzer/CMakeLists.txt
@@ -95,6 +95,8 @@
         cli.h
         fuzzer.cc
         override_cli_params.h
+        ../apply_substitute_overrides.cc
+        ../apply_substitute_overrides.h
         ../tint_common_fuzzer.cc
         ../tint_common_fuzzer.h)
 
diff --git a/src/tint/fuzzers/tint_common_fuzzer.cc b/src/tint/fuzzers/tint_common_fuzzer.cc
index 6fa3b6e..02d2d4d 100644
--- a/src/tint/fuzzers/tint_common_fuzzer.cc
+++ b/src/tint/fuzzers/tint_common_fuzzer.cc
@@ -32,6 +32,7 @@
 
 #include "src/tint/ast/module.h"
 #include "src/tint/diagnostic/formatter.h"
+#include "src/tint/fuzzers/apply_substitute_overrides.h"
 #include "src/tint/program.h"
 #include "src/tint/sem/binding_point.h"
 #include "src/tint/sem/variable.h"
@@ -234,32 +235,9 @@
 
     {
         // Run SubstituteOverride if required
-
-        ast::transform::SubstituteOverride::Config cfg;
-        inspector::Inspector inspector(&program);
-        auto default_values = inspector.GetOverrideDefaultValues();
-        for (const auto& [override_id, scalar] : default_values) {
-            // If the override is not null, then it has a default value, we can just let it use the
-            // provided default instead of overriding.
-            if (!scalar.IsNull()) {
-                continue;
-            }
-
-            cfg.map.insert({override_id, 0.0});
-        }
-
-        if (!default_values.empty()) {
-            transform::DataMap override_data;
-            override_data.Add<ast::transform::SubstituteOverride::Config>(cfg);
-
-            transform::Manager mgr;
-            mgr.append(std::make_unique<ast::transform::SubstituteOverride>());
-
-            transform::DataMap outputs;
-            auto out = mgr.Run(&program, override_data, outputs);
-            if (!validate_program(out)) {
-                return 0;
-            }
+        auto out = ApplySubstituteOverrides(std::move(program));
+        if (!validate_program(out)) {
+            return 0;
         }
     }
 
diff --git a/src/tint/fuzzers/tint_concurrency_fuzzer.cc b/src/tint/fuzzers/tint_concurrency_fuzzer.cc
index e4359dc..f2341a7 100644
--- a/src/tint/fuzzers/tint_concurrency_fuzzer.cc
+++ b/src/tint/fuzzers/tint_concurrency_fuzzer.cc
@@ -19,6 +19,7 @@
 
 #include <thread>
 
+#include "src/tint/fuzzers/apply_substitute_overrides.h"
 #include "src/tint/inspector/inspector.h"
 #include "src/tint/reader/wgsl/parser.h"
 #include "src/tint/utils/hash.h"
@@ -47,6 +48,8 @@
         return 0;
     }
 
+    program = tint::fuzzers::ApplySubstituteOverrides(std::move(program));
+
     tint::inspector::Inspector inspector(&program);
     auto entry_points = inspector.GetEntryPoints();
     std::string entry_point = entry_points.empty() ? "" : entry_points.front().name;
diff --git a/src/tint/fuzzers/tint_regex_fuzzer/CMakeLists.txt b/src/tint/fuzzers/tint_regex_fuzzer/CMakeLists.txt
index bcd0885..de05287 100644
--- a/src/tint/fuzzers/tint_regex_fuzzer/CMakeLists.txt
+++ b/src/tint/fuzzers/tint_regex_fuzzer/CMakeLists.txt
@@ -39,6 +39,8 @@
         cli.h
         fuzzer.cc
         override_cli_params.h
+        ../apply_substitute_overrides.cc
+        ../apply_substitute_overrides.h
         ../tint_common_fuzzer.cc
         ../tint_common_fuzzer.h)
 
diff --git a/src/tint/fuzzers/tint_spirv_tools_fuzzer/CMakeLists.txt b/src/tint/fuzzers/tint_spirv_tools_fuzzer/CMakeLists.txt
index c83333a..3d6c37b 100644
--- a/src/tint/fuzzers/tint_spirv_tools_fuzzer/CMakeLists.txt
+++ b/src/tint/fuzzers/tint_spirv_tools_fuzzer/CMakeLists.txt
@@ -39,6 +39,8 @@
         util.h)
 
 set(FUZZER_SOURCES ${FUZZER_SOURCES}
+        ../apply_substitute_overrides.cc
+        ../apply_substitute_overrides.h
         ../tint_common_fuzzer.cc
         ../tint_common_fuzzer.h)
 
diff --git a/src/tint/ir/disassembler.cc b/src/tint/ir/disassembler.cc
index 03c88ee..f8e301f 100644
--- a/src/tint/ir/disassembler.cc
+++ b/src/tint/ir/disassembler.cc
@@ -42,7 +42,6 @@
 #include "src/tint/ir/store.h"
 #include "src/tint/ir/switch.h"
 #include "src/tint/ir/swizzle.h"
-#include "src/tint/ir/transform/block_decorated_structs.h"
 #include "src/tint/ir/unreachable.h"
 #include "src/tint/ir/user_call.h"
 #include "src/tint/ir/var.h"
diff --git a/src/tint/reader/spirv/parser_impl_test_helper.cc b/src/tint/reader/spirv/parser_impl_test_helper.cc
index 697a51b..5fd4ffa 100644
--- a/src/tint/reader/spirv/parser_impl_test_helper.cc
+++ b/src/tint/reader/spirv/parser_impl_test_helper.cc
@@ -42,7 +42,7 @@
     if (!writer.Diagnostics().empty()) {
         return "WGSL writer error: " + writer.Diagnostics().str();
     }
-    return writer.result();
+    return writer.Result();
 }
 
 std::string ToString(const Program& program, utils::VectorRef<const ast::Statement*> stmts) {
@@ -53,7 +53,7 @@
     if (!writer.Diagnostics().empty()) {
         return "WGSL writer error: " + writer.Diagnostics().str();
     }
-    return writer.result();
+    return writer.Result();
 }
 
 std::string ToString(const Program& program, const ast::Node* node) {
@@ -73,7 +73,7 @@
             if (!writer.Diagnostics().empty()) {
                 return "WGSL writer error: " + writer.Diagnostics().str();
             }
-            return writer.result();
+            return writer.Result();
         },
         [&](const ast::Identifier* ident) { return ident->symbol.Name(); },
         [&](Default) {
diff --git a/src/tint/resolver/validator.cc b/src/tint/resolver/validator.cc
index 3ef674e..c02e123 100644
--- a/src/tint/resolver/validator.cc
+++ b/src/tint/resolver/validator.cc
@@ -1237,32 +1237,32 @@
     };
 
     // Outer lambda for validating the entry point attributes for a type.
-    auto validate_entry_point_attributes =
-        [&](utils::VectorRef<const ast::Attribute*> attrs, const type::Type* ty, Source source,
-            ParamOrRetType param_or_ret, std::optional<uint32_t> location,
-            std::optional<uint32_t> index) {
-            if (!validate_entry_point_attributes_inner(attrs, ty, source, param_or_ret,
-                                                       /*is_struct_member*/ false, location,
-                                                       index)) {
-                return false;
-            }
+    auto validate_entry_point_attributes = [&](utils::VectorRef<const ast::Attribute*> attrs,
+                                               const type::Type* ty, Source source,
+                                               ParamOrRetType param_or_ret,
+                                               std::optional<uint32_t> location,
+                                               std::optional<uint32_t> index) {
+        if (!validate_entry_point_attributes_inner(attrs, ty, source, param_or_ret,
+                                                   /*is_struct_member*/ false, location, index)) {
+            return false;
+        }
 
-            if (auto* str = ty->As<sem::Struct>()) {
-                for (auto* member : str->Members()) {
-                    if (!validate_entry_point_attributes_inner(
-                            member->Declaration()->attributes, member->Type(),
-                            member->Declaration()->source, param_or_ret,
-                            /*is_struct_member*/ true, member->Attributes().location,
-                            member->Attributes().index)) {
-                        AddNote("while analyzing entry point '" + decl->name->symbol.Name() + "'",
-                                decl->source);
-                        return false;
-                    }
+        if (auto* str = ty->As<sem::Struct>()) {
+            for (auto* member : str->Members()) {
+                if (!validate_entry_point_attributes_inner(
+                        member->Declaration()->attributes, member->Type(),
+                        member->Declaration()->source, param_or_ret,
+                        /*is_struct_member*/ true, member->Attributes().location,
+                        member->Attributes().index)) {
+                    AddNote("while analyzing entry point '" + decl->name->symbol.Name() + "'",
+                            decl->source);
+                    return false;
                 }
             }
+        }
 
-            return true;
-        };
+        return true;
+    };
 
     for (auto* param : func->Parameters()) {
         auto* param_decl = param->Declaration();
diff --git a/src/tint/type/manager.cc b/src/tint/type/manager.cc
index 89a0c0a..17a3011 100644
--- a/src/tint/type/manager.cc
+++ b/src/tint/type/manager.cc
@@ -72,6 +72,14 @@
     return Get<type::AbstractInt>();
 }
 
+const type::Atomic* Manager::atomic(const type::Type* inner) {
+    return Get<type::Atomic>(inner);
+}
+
+const type::Vector* Manager::packed_vec(const type::Type* inner, uint32_t size) {
+    return Get<type::Vector>(inner, size, true);
+}
+
 const type::Vector* Manager::vec(const type::Type* inner, uint32_t size) {
     return Get<type::Vector>(inner, size);
 }
diff --git a/src/tint/type/manager.h b/src/tint/type/manager.h
index 99ffda3..63e02e3 100644
--- a/src/tint/type/manager.h
+++ b/src/tint/type/manager.h
@@ -22,6 +22,8 @@
 #include "src/tint/builtin/fluent_types.h"
 #include "src/tint/builtin/number.h"
 #include "src/tint/symbol.h"
+#include "src/tint/type/atomic.h"
+#include "src/tint/type/sampler.h"
 #include "src/tint/type/struct.h"
 #include "src/tint/type/type.h"
 #include "src/tint/type/unique_node.h"
@@ -158,6 +160,22 @@
     const type::AbstractInt* AInt();
 
     /// @param inner the inner type
+    /// @returns an atomic type with the element type @p inner
+    const type::Atomic* atomic(const type::Type* inner);
+
+    /// @tparam T the element type
+    /// @returns the atomic type
+    template <typename T>
+    const type::Atomic* atomic() {
+        return atomic(Get<T>());
+    }
+
+    /// @param inner the inner type
+    /// @param size the vector size
+    /// @returns the vector type
+    const type::Vector* packed_vec(const type::Type* inner, uint32_t size);
+
+    /// @param inner the inner type
     /// @param size the vector size
     /// @returns the vector type
     const type::Vector* vec(const type::Type* inner, uint32_t size);
@@ -389,6 +407,14 @@
         return ptr(SPACE, subtype, ACCESS);
     }
 
+    /// @returns the sampler type
+    const type::Sampler* sampler() { return Get<type::Sampler>(type::SamplerKind::kSampler); }
+
+    /// @returns the comparison sampler type
+    const type::Sampler* comparison_sampler() {
+        return Get<type::Sampler>(type::SamplerKind::kComparisonSampler);
+    }
+
     /// A structure member descriptor.
     struct StructMemberDesc {
         /// The name of the struct member.
diff --git a/src/tint/writer/ast_text_generator.cc b/src/tint/writer/ast_text_generator.cc
index dc0530b..65bf618 100644
--- a/src/tint/writer/ast_text_generator.cc
+++ b/src/tint/writer/ast_text_generator.cc
@@ -30,13 +30,4 @@
     return builder_.Symbols().New(prefix).Name();
 }
 
-std::string ASTTextGenerator::StructName(const type::Struct* s) {
-    auto name = s->Name().Name();
-    if (name.size() > 1 && name[0] == '_' && name[1] == '_') {
-        name = utils::GetOrCreate(builtin_struct_names_, s,
-                                  [&] { return UniqueIdentifier(name.substr(2)); });
-    }
-    return name;
-}
-
 }  // namespace tint::writer
diff --git a/src/tint/writer/ast_text_generator.h b/src/tint/writer/ast_text_generator.h
index 243458c..d385e33 100644
--- a/src/tint/writer/ast_text_generator.h
+++ b/src/tint/writer/ast_text_generator.h
@@ -31,19 +31,12 @@
     /// Constructor
     /// @param program the program used by the generator
     explicit ASTTextGenerator(const Program* program);
-    ~ASTTextGenerator();
+    ~ASTTextGenerator() override;
 
     /// @return a new, unique identifier with the given prefix.
     /// @param prefix optional prefix to apply to the generated identifier. If
     /// empty "tint_symbol" will be used.
-    std::string UniqueIdentifier(const std::string& prefix = "");
-
-    /// @param s the semantic structure
-    /// @returns the name of the structure, taking special care of builtin
-    /// structures that start with double underscores. If the structure is a
-    /// builtin, then the returned name will be a unique name without the leading
-    /// underscores.
-    std::string StructName(const type::Struct* s);
+    std::string UniqueIdentifier(const std::string& prefix = "") override;
 
   protected:
     /// @returns the resolved type of the ast::Expression `expr`
diff --git a/src/tint/writer/glsl/generator.cc b/src/tint/writer/glsl/generator.cc
index 24b7597..4b4d1b8 100644
--- a/src/tint/writer/glsl/generator.cc
+++ b/src/tint/writer/glsl/generator.cc
@@ -48,7 +48,7 @@
     impl->Generate();
     result.success = impl->Diagnostics().empty();
     result.error = impl->Diagnostics().str();
-    result.glsl = impl->result();
+    result.glsl = impl->Result();
 
     // Collect the list of entry points in the sanitized program.
     for (auto* func : sanitized_result.program.AST().Functions()) {
diff --git a/src/tint/writer/glsl/generator_impl.cc b/src/tint/writer/glsl/generator_impl.cc
index 537d328..92f182a 100644
--- a/src/tint/writer/glsl/generator_impl.cc
+++ b/src/tint/writer/glsl/generator_impl.cc
@@ -260,7 +260,7 @@
 
 void GeneratorImpl::Generate() {
     {
-        auto out = line();
+        auto out = Line();
         out << "#version " << version_.major_version << version_.minor_version << "0";
         if (version_.IsES()) {
             out << " es";
@@ -269,7 +269,7 @@
 
     auto helpers_insertion_point = current_buffer_->lines.size();
 
-    line();
+    Line();
 
     auto* mod = builder_.Sem().Module();
     for (auto* decl : mod->DependencyOrderedDeclarations()) {
@@ -387,7 +387,7 @@
 }
 
 void GeneratorImpl::EmitAssign(const ast::AssignmentStatement* stmt) {
-    auto out = line();
+    auto out = Line();
     EmitExpression(out, stmt->lhs);
     out << " = ";
     EmitExpression(out, stmt->rhs);
@@ -470,7 +470,7 @@
                                 auto fn_name = UniqueIdentifier("tint_float_modulo");
                                 std::vector<std::string> parameter_names;
                                 {
-                                    auto decl = line(&b);
+                                    auto decl = Line(&b);
                                     EmitTypeAndName(decl, ret_ty, builtin::AddressSpace::kUndefined,
                                                     builtin::Access::kUndefined, fn_name);
                                     {
@@ -487,10 +487,10 @@
                                 }
                                 {
                                     ScopedIndent si(&b);
-                                    line(&b) << "return (lhs - rhs * trunc(lhs / rhs));";
+                                    Line(&b) << "return (lhs - rhs * trunc(lhs / rhs));";
                                 }
-                                line(&b) << "}";
-                                line(&b);
+                                Line(&b) << "}";
+                                Line(&b);
                                 return fn_name;
                             });
 
@@ -514,27 +514,27 @@
         auto name = UniqueIdentifier(kTempNamePrefix);
 
         {
-            auto pre = line();
+            auto pre = Line();
             pre << "bool " << name << " = ";
             EmitExpression(pre, expr->lhs);
             pre << ";";
         }
 
         if (expr->op == ast::BinaryOp::kLogicalOr) {
-            line() << "if (!" << name << ") {";
+            Line() << "if (!" << name << ") {";
         } else {
-            line() << "if (" << name << ") {";
+            Line() << "if (" << name << ") {";
         }
 
         {
             ScopedIndent si(this);
-            auto pre = line();
+            auto pre = Line();
             pre << name << " = ";
             EmitExpression(pre, expr->rhs);
             pre << ";";
         }
 
-        line() << "}";
+        Line() << "}";
 
         out << "(" << name << ")";
         return;
@@ -633,17 +633,17 @@
 }
 
 void GeneratorImpl::EmitBlock(const ast::BlockStatement* stmt) {
-    line() << "{";
+    Line() << "{";
     EmitStatementsWithIndent(stmt->statements);
-    line() << "}";
+    Line() << "}";
 }
 
 void GeneratorImpl::EmitBreak(const ast::BreakStatement*) {
-    line() << "break;";
+    Line() << "break;";
 }
 
 void GeneratorImpl::EmitBreakIf(const ast::BreakIfStatement* b) {
-    auto out = line();
+    auto out = Line();
     out << "if (";
     EmitExpression(out, b->condition);
     out << ") { break; }";
@@ -825,13 +825,13 @@
             std::string result = UniqueIdentifier("atomic_compare_result");
 
             {
-                auto pre = line();
+                auto pre = Line();
                 EmitTypeAndName(pre, builtin->ReturnType(), builtin::AddressSpace::kUndefined,
                                 builtin::Access::kUndefined, result);
                 pre << ";";
             }
             {
-                auto pre = line();
+                auto pre = Line();
                 pre << result << ".old_value = atomicCompSwap";
                 {
                     ScopedParen sp(pre);
@@ -844,7 +844,7 @@
                 pre << ";";
             }
             {
-                auto pre = line();
+                auto pre = Line();
                 pre << result << ".exchanged = " << result << ".old_value == ";
                 EmitExpression(pre, compare_value);
                 pre << ";";
@@ -950,7 +950,7 @@
     if (auto* vec = builtin->Parameters()[2]->Type()->As<type::Vector>()) {
         CallBuiltinHelper(out, expr, builtin,
                           [&](TextBuffer* b, const std::vector<std::string>& params) {
-                              auto l = line(b);
+                              auto l = Line(b);
                               l << "  return ";
                               EmitType(l, builtin->ReturnType(), builtin::AddressSpace::kUndefined,
                                        builtin::Access::kUndefined, "");
@@ -1004,7 +1004,7 @@
                 v = s.str();
             }
             {  // (u)int tint_int_dot([i|u]vecN a, [i|u]vecN b) {
-                auto l = line(&b);
+                auto l = Line(&b);
                 EmitType(l, vec_ty->type(), builtin::AddressSpace::kUndefined,
                          builtin::Access::kRead, "");
                 l << " " << fn_name << "(";
@@ -1014,7 +1014,7 @@
                 l << " b) {";
             }
             {
-                auto l = line(&b);
+                auto l = Line(&b);
                 l << "  return ";
                 for (uint32_t i = 0; i < vec_ty->Width(); i++) {
                     if (i > 0) {
@@ -1024,7 +1024,7 @@
                 }
                 l << ";";
             }
-            line(&b) << "}";
+            Line(&b) << "}";
             return fn_name;
         });
     }
@@ -1048,13 +1048,13 @@
                           EmitStructType(&helpers_, builtin->ReturnType()->As<type::Struct>());
 
                           {
-                              auto l = line(b);
+                              auto l = Line(b);
                               EmitType(l, builtin->ReturnType(), builtin::AddressSpace::kUndefined,
                                        builtin::Access::kUndefined, "");
                               l << " result;";
                           }
-                          line(b) << "result.fract = modf(" << params[0] << ", result.whole);";
-                          line(b) << "return result;";
+                          Line(b) << "result.fract = modf(" << params[0] << ", result.whole);";
+                          Line(b) << "return result;";
                       });
 }
 
@@ -1069,13 +1069,13 @@
                           EmitStructType(&helpers_, builtin->ReturnType()->As<type::Struct>());
 
                           {
-                              auto l = line(b);
+                              auto l = Line(b);
                               EmitType(l, builtin->ReturnType(), builtin::AddressSpace::kUndefined,
                                        builtin::Access::kUndefined, "");
                               l << " result;";
                           }
-                          line(b) << "result.fract = frexp(" << params[0] << ", result.exp);";
-                          line(b) << "return result;";
+                          Line(b) << "result.fract = frexp(" << params[0] << ", result.exp);";
+                          Line(b) << "return result;";
                       });
 }
 
@@ -1086,7 +1086,7 @@
     const std::string suffix = Is<type::F16>(return_elem_type) ? "hf" : "f";
     CallBuiltinHelper(out, expr, builtin,
                       [&](TextBuffer* b, const std::vector<std::string>& params) {
-                          line(b) << "return " << params[0] << " * " << std::setprecision(20)
+                          Line(b) << "return " << params[0] << " * " << std::setprecision(20)
                                   << sem::kRadToDeg << suffix << ";";
                       });
 }
@@ -1098,7 +1098,7 @@
     const std::string suffix = Is<type::F16>(return_elem_type) ? "hf" : "f";
     CallBuiltinHelper(out, expr, builtin,
                       [&](TextBuffer* b, const std::vector<std::string>& params) {
-                          line(b) << "return " << params[0] << " * " << std::setprecision(20)
+                          Line(b) << "return " << params[0] << " * " << std::setprecision(20)
                                   << sem::kDegToRad << suffix << ";";
                       });
 }
@@ -1113,24 +1113,24 @@
             if (auto* vec = builtin->ReturnType()->As<type::Vector>()) {
                 switch (vec->Width()) {
                     case 2: {
-                        line(b) << "return unpackHalf2x16(packHalf2x16(" << v << "));";
+                        Line(b) << "return unpackHalf2x16(packHalf2x16(" << v << "));";
                         return;
                     }
                     case 3: {
-                        line(b) << "return vec3(";
-                        line(b) << "  unpackHalf2x16(packHalf2x16(" << v << ".xy)),";
-                        line(b) << "  unpackHalf2x16(packHalf2x16(" << v << ".zz)).x);";
+                        Line(b) << "return vec3(";
+                        Line(b) << "  unpackHalf2x16(packHalf2x16(" << v << ".xy)),";
+                        Line(b) << "  unpackHalf2x16(packHalf2x16(" << v << ".zz)).x);";
                         return;
                     }
                     default: {
-                        line(b) << "return vec4(";
-                        line(b) << "  unpackHalf2x16(packHalf2x16(" << v << ".xy)),";
-                        line(b) << "  unpackHalf2x16(packHalf2x16(" << v << ".zw)));";
+                        Line(b) << "return vec4(";
+                        Line(b) << "  unpackHalf2x16(packHalf2x16(" << v << ".xy)),";
+                        Line(b) << "  unpackHalf2x16(packHalf2x16(" << v << ".zw)));";
                         return;
                     }
                 }
             }
-            line(b) << "return unpackHalf2x16(packHalf2x16(vec2(" << v << "))).x;";
+            Line(b) << "return unpackHalf2x16(packHalf2x16(vec2(" << v << "))).x;";
         });
 }
 
@@ -1577,7 +1577,7 @@
 void GeneratorImpl::EmitCase(const ast::CaseStatement* stmt) {
     auto* sem = builder_.Sem().Get<sem::CaseStatement>(stmt);
     for (auto* selector : sem->Selectors()) {
-        auto out = line();
+        auto out = Line();
 
         if (selector->IsDefault()) {
             out << "default";
@@ -1595,24 +1595,24 @@
         ScopedIndent si(this);
         EmitStatements(stmt->body->statements);
         if (!last_is_break(stmt->body)) {
-            line() << "break;";
+            Line() << "break;";
         }
     }
 
-    line() << "}";
+    Line() << "}";
 }
 
 void GeneratorImpl::EmitContinue(const ast::ContinueStatement*) {
     if (emit_continuing_) {
         emit_continuing_();
     }
-    line() << "continue;";
+    Line() << "continue;";
 }
 
 void GeneratorImpl::EmitDiscard(const ast::DiscardStatement*) {
     // TODO(dsinclair): Verify this is correct when the discard semantics are
     // defined for WGSL (https://github.com/gpuweb/gpuweb/issues/361)
-    line() << "discard;";
+    Line() << "discard;";
 }
 
 void GeneratorImpl::EmitExpression(utils::StringStream& out, const ast::Expression* expr) {
@@ -1645,7 +1645,7 @@
 
 void GeneratorImpl::EmitIf(const ast::IfStatement* stmt) {
     {
-        auto out = line();
+        auto out = Line();
         out << "if (";
         EmitExpression(out, stmt->condition);
         out << ") {";
@@ -1653,14 +1653,14 @@
     EmitStatementsWithIndent(stmt->body->statements);
 
     if (stmt->else_statement) {
-        line() << "} else {";
+        Line() << "} else {";
         if (auto* block = stmt->else_statement->As<ast::BlockStatement>()) {
             EmitStatementsWithIndent(block->statements);
         } else {
             EmitStatementsWithIndent(utils::Vector{stmt->else_statement});
         }
     }
-    line() << "}";
+    Line() << "}";
 }
 
 void GeneratorImpl::EmitFunction(const ast::Function* func) {
@@ -1672,7 +1672,7 @@
     }
 
     {
-        auto out = line();
+        auto out = Line();
         auto name = func->name->symbol.Name();
         EmitType(out, sem->ReturnType(), builtin::AddressSpace::kUndefined,
                  builtin::Access::kReadWrite, "");
@@ -1710,8 +1710,8 @@
 
     EmitStatementsWithIndent(func->body->statements);
 
-    line() << "}";
-    line();
+    Line() << "}";
+    Line();
 }
 
 void GeneratorImpl::EmitGlobalVariable(const ast::Variable* global) {
@@ -1776,14 +1776,14 @@
     }
     auto bp = *sem->As<sem::GlobalVariable>()->BindingPoint();
     {
-        auto out = line();
+        auto out = Line();
         out << "layout(binding = " << bp.binding << ", std140";
         out << ") uniform " << UniqueIdentifier(StructName(str) + "_ubo") << " {";
     }
     EmitStructMembers(current_buffer_, str);
     auto name = var->name->symbol.Name();
-    line() << "} " << name << ";";
-    line();
+    Line() << "} " << name << ";";
+    Line();
 }
 
 void GeneratorImpl::EmitStorageVariable(const ast::Var* var, const sem::Variable* sem) {
@@ -1794,16 +1794,16 @@
         return;
     }
     auto bp = *sem->As<sem::GlobalVariable>()->BindingPoint();
-    line() << "layout(binding = " << bp.binding << ", std430) buffer "
+    Line() << "layout(binding = " << bp.binding << ", std430) buffer "
            << UniqueIdentifier(StructName(str) + "_ssbo") << " {";
     EmitStructMembers(current_buffer_, str);
     auto name = var->name->symbol.Name();
-    line() << "} " << name << ";";
-    line();
+    Line() << "} " << name << ";";
+    Line();
 }
 
 void GeneratorImpl::EmitHandleVariable(const ast::Var* var, const sem::Variable* sem) {
-    auto out = line();
+    auto out = Line();
 
     auto name = var->name->symbol.Name();
     auto* type = sem->Type()->UnwrapRef();
@@ -1879,7 +1879,7 @@
 
 void GeneratorImpl::EmitPrivateVariable(const sem::Variable* var) {
     auto* decl = var->Declaration();
-    auto out = line();
+    auto out = Line();
 
     auto name = decl->name->symbol.Name();
     auto* type = var->Type()->UnwrapRef();
@@ -1896,7 +1896,7 @@
 
 void GeneratorImpl::EmitWorkgroupVariable(const sem::Variable* var) {
     auto* decl = var->Declaration();
-    auto out = line();
+    auto out = Line();
 
     out << "shared ";
 
@@ -1925,7 +1925,7 @@
         return;
     }
 
-    auto out = line();
+    auto out = Line();
     EmitAttributes(out, var, decl->attributes);
     EmitInterpolationQualifiers(out, decl->attributes);
 
@@ -2005,7 +2005,7 @@
     }
 
     if (func->PipelineStage() == ast::PipelineStage::kCompute) {
-        auto out = line();
+        auto out = Line();
         // Emit the layout(local_size) attributes.
         auto wgsize = func_sem->WorkgroupSize();
         out << "layout(";
@@ -2029,7 +2029,7 @@
 
     // Emit original entry point signature
     {
-        auto out = line();
+        auto out = Line();
         EmitTypeAndName(out, func_sem->ReturnType(), builtin::AddressSpace::kUndefined,
                         builtin::Access::kUndefined, func->name->symbol.Name());
         out << "(";
@@ -2062,7 +2062,7 @@
     {
         ScopedIndent si(this);
         if (func->PipelineStage() == ast::PipelineStage::kVertex) {
-            line() << "gl_PointSize = 1.0;";
+            Line() << "gl_PointSize = 1.0;";
         }
 
         EmitStatements(func->body->statements);
@@ -2073,7 +2073,7 @@
         }
     }
 
-    line() << "}";
+    Line() << "}";
 }
 
 void GeneratorImpl::EmitConstant(utils::StringStream& out, const constant::Value* constant) {
@@ -2251,23 +2251,23 @@
     };
 
     TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
-    line() << "while (true) {";
+    Line() << "while (true) {";
     {
         ScopedIndent si(this);
         EmitStatements(stmt->body->statements);
         emit_continuing_();
     }
-    line() << "}";
+    Line() << "}";
 }
 
 void GeneratorImpl::EmitForLoop(const ast::ForLoopStatement* stmt) {
     // Nest a for loop with a new block. In HLSL the initializer scope is not
     // nested by the for-loop, so we may get variable redefinitions.
-    line() << "{";
-    increment_indent();
+    Line() << "{";
+    IncrementIndent();
     TINT_DEFER({
-        decrement_indent();
-        line() << "}";
+        DecrementIndent();
+        Line() << "}";
     });
 
     TextBuffer init_buf;
@@ -2306,16 +2306,16 @@
         auto emit_continuing = [&] { current_buffer_->Append(cont_buf); };
 
         TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
-        line() << "while (true) {";
-        increment_indent();
+        Line() << "while (true) {";
+        IncrementIndent();
         TINT_DEFER({
-            decrement_indent();
-            line() << "}";
+            DecrementIndent();
+            Line() << "}";
         });
 
         if (stmt->condition) {
             current_buffer_->Append(cond_pre);
-            line() << "if (!(" << cond_buf.str() << ")) { break; }";
+            Line() << "if (!(" << cond_buf.str() << ")) { break; }";
         }
 
         EmitStatements(stmt->body->statements);
@@ -2323,7 +2323,7 @@
     } else {
         // For-loop can be generated.
         {
-            auto out = line();
+            auto out = Line();
             out << "for";
             {
                 ScopedParen sp(out);
@@ -2347,7 +2347,7 @@
             TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
             EmitStatementsWithIndent(stmt->body->statements);
         }
-        line() << "}";
+        Line() << "}";
     }
 }
 
@@ -2367,21 +2367,21 @@
     // as a regular while in GLSL. Instead we need to generate a `while(true)` loop.
     bool emit_as_loop = cond_pre.lines.size() > 0;
     if (emit_as_loop) {
-        line() << "while (true) {";
-        increment_indent();
+        Line() << "while (true) {";
+        IncrementIndent();
         TINT_DEFER({
-            decrement_indent();
-            line() << "}";
+            DecrementIndent();
+            Line() << "}";
         });
 
         current_buffer_->Append(cond_pre);
-        line() << "if (!(" << cond_buf.str() << ")) { break; }";
+        Line() << "if (!(" << cond_buf.str() << ")) { break; }";
 
         EmitStatements(stmt->body->statements);
     } else {
         // While can be generated.
         {
-            auto out = line();
+            auto out = Line();
             out << "while";
             {
                 ScopedParen sp(out);
@@ -2390,7 +2390,7 @@
             out << " {";
         }
         EmitStatementsWithIndent(stmt->body->statements);
-        line() << "}";
+        Line() << "}";
     }
 }
 
@@ -2418,12 +2418,12 @@
 
 void GeneratorImpl::EmitReturn(const ast::ReturnStatement* stmt) {
     if (stmt->value) {
-        auto out = line();
+        auto out = Line();
         out << "return ";
         EmitExpression(out, stmt->value);
         out << ";";
     } else {
-        line() << "return;";
+        Line() << "return;";
     }
 }
 
@@ -2435,7 +2435,7 @@
         [&](const ast::BreakStatement* b) { EmitBreak(b); },
         [&](const ast::BreakIfStatement* b) { EmitBreakIf(b); },
         [&](const ast::CallStatement* c) {
-            auto out = line();
+            auto out = Line();
             EmitCall(out, c->expr);
             out << ";";
         },
@@ -2471,7 +2471,7 @@
 
 void GeneratorImpl::EmitSwitch(const ast::SwitchStatement* stmt) {
     {  // switch(expr) {
-        auto out = line();
+        auto out = Line();
         out << "switch(";
         EmitExpression(out, stmt->condition);
         out << ") {";
@@ -2484,7 +2484,7 @@
         }
     }
 
-    line() << "}";
+    Line() << "}";
 }
 
 void GeneratorImpl::EmitType(utils::StringStream& out,
@@ -2675,10 +2675,10 @@
     }
 
     auto address_space_uses = str->AddressSpaceUsage();
-    line(b) << "struct " << StructName(str) << " {";
+    Line(b) << "struct " << StructName(str) << " {";
     EmitStructMembers(b, str);
-    line(b) << "};";
-    line(b);
+    Line(b) << "};";
+    Line(b);
 }
 
 void GeneratorImpl::EmitStructMembers(TextBuffer* b, const type::Struct* str) {
@@ -2687,7 +2687,7 @@
         auto name = mem->Name().Name();
         auto* ty = mem->Type();
 
-        auto out = line(b);
+        auto out = Line(b);
         EmitTypeAndName(out, ty, builtin::AddressSpace::kUndefined, builtin::Access::kReadWrite,
                         name);
         out << ";";
@@ -2723,7 +2723,7 @@
     auto* sem = builder_.Sem().Get(var);
     auto* type = sem->Type()->UnwrapRef();
 
-    auto out = line();
+    auto out = Line();
     EmitTypeAndName(out, type, sem->AddressSpace(), sem->Access(), var->name->symbol.Name());
 
     out << " = ";
@@ -2740,7 +2740,7 @@
     auto* sem = builder_.Sem().Get(let);
     auto* type = sem->Type()->UnwrapRef();
 
-    auto out = line();
+    auto out = Line();
     // TODO(senorblanco): handle const
     EmitTypeAndName(out, type, builtin::AddressSpace::kUndefined, builtin::Access::kUndefined,
                     let->name->symbol.Name());
@@ -2754,7 +2754,7 @@
     auto* sem = builder_.Sem().Get(var);
     auto* type = sem->Type();
 
-    auto out = line();
+    auto out = Line();
     out << "const ";
     EmitTypeAndName(out, type, builtin::AddressSpace::kUndefined, builtin::Access::kUndefined,
                     var->name->symbol.Name());
@@ -2776,7 +2776,7 @@
         auto fn_name = UniqueIdentifier(std::string("tint_") + builtin::str(builtin->Type()));
         std::vector<std::string> parameter_names;
         {
-            auto decl = line(&b);
+            auto decl = Line(&b);
             EmitTypeAndName(decl, builtin->ReturnType(), builtin::AddressSpace::kUndefined,
                             builtin::Access::kUndefined, fn_name);
             {
@@ -2802,8 +2802,8 @@
             ScopedIndent si(&b);
             build(&b, parameter_names);
         }
-        line(&b) << "}";
-        line(&b);
+        Line(&b) << "}";
+        Line(&b);
         return fn_name;
     });
 
diff --git a/src/tint/writer/glsl/generator_impl.h b/src/tint/writer/glsl/generator_impl.h
index 23633ae..8650647 100644
--- a/src/tint/writer/glsl/generator_impl.h
+++ b/src/tint/writer/glsl/generator_impl.h
@@ -81,7 +81,7 @@
     /// @param program the program to generate
     /// @param version the GLSL version to use
     GeneratorImpl(const Program* program, const Version& version);
-    ~GeneratorImpl();
+    ~GeneratorImpl() override;
 
     /// Generates the GLSL shader
     void Generate();
diff --git a/src/tint/writer/glsl/generator_impl_assign_test.cc b/src/tint/writer/glsl/generator_impl_assign_test.cc
index 0adcac2..a6c75d5 100644
--- a/src/tint/writer/glsl/generator_impl_assign_test.cc
+++ b/src/tint/writer/glsl/generator_impl_assign_test.cc
@@ -29,11 +29,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(assign);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), "  lhs = rhs;\n");
+    EXPECT_EQ(gen.Result(), "  lhs = rhs;\n");
 }
 
 }  // namespace
diff --git a/src/tint/writer/glsl/generator_impl_binary_test.cc b/src/tint/writer/glsl/generator_impl_binary_test.cc
index 7ca2b09..0907a01 100644
--- a/src/tint/writer/glsl/generator_impl_binary_test.cc
+++ b/src/tint/writer/glsl/generator_impl_binary_test.cc
@@ -544,7 +544,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 vec3 tint_float_modulo(vec3 lhs, vec3 rhs) {
   return (lhs - rhs * trunc(lhs / rhs));
@@ -589,7 +589,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 #extension GL_AMD_gpu_shader_half_float : require
 
 f16vec3 tint_float_modulo(f16vec3 lhs, f16vec3 rhs) {
@@ -630,7 +630,7 @@
     gen.EmitExpression(out, expr);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
     EXPECT_EQ(out.str(), "(tint_tmp)");
-    EXPECT_EQ(gen.result(), R"(bool tint_tmp = a;
+    EXPECT_EQ(gen.Result(), R"(bool tint_tmp = a;
 if (tint_tmp) {
   tint_tmp = b;
 }
@@ -656,7 +656,7 @@
     gen.EmitExpression(out, expr);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
     EXPECT_EQ(out.str(), "(tint_tmp)");
-    EXPECT_EQ(gen.result(), R"(bool tint_tmp_1 = a;
+    EXPECT_EQ(gen.Result(), R"(bool tint_tmp_1 = a;
 if (tint_tmp_1) {
   tint_tmp_1 = b;
 }
@@ -684,7 +684,7 @@
     gen.EmitExpression(out, expr);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
     EXPECT_EQ(out.str(), "(tint_tmp)");
-    EXPECT_EQ(gen.result(), R"(bool tint_tmp = a;
+    EXPECT_EQ(gen.Result(), R"(bool tint_tmp = a;
 if (!tint_tmp) {
   tint_tmp = b;
 }
@@ -715,7 +715,7 @@
 
     gen.EmitStatement(expr);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(bool tint_tmp = a;
+    EXPECT_EQ(gen.Result(), R"(bool tint_tmp = a;
 if (tint_tmp) {
   tint_tmp = b;
 }
@@ -752,7 +752,7 @@
 
     gen.EmitStatement(expr);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(bool tint_tmp_1 = a;
+    EXPECT_EQ(gen.Result(), R"(bool tint_tmp_1 = a;
 if (tint_tmp_1) {
   tint_tmp_1 = b;
 }
@@ -784,7 +784,7 @@
 
     gen.EmitStatement(expr);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(bool tint_tmp_1 = b;
+    EXPECT_EQ(gen.Result(), R"(bool tint_tmp_1 = b;
 if (!tint_tmp_1) {
   tint_tmp_1 = c;
 }
@@ -817,7 +817,7 @@
 
     gen.EmitStatement(decl);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(bool tint_tmp_1 = b;
+    EXPECT_EQ(gen.Result(), R"(bool tint_tmp_1 = b;
 if (tint_tmp_1) {
   tint_tmp_1 = c;
 }
@@ -860,7 +860,7 @@
 
     gen.EmitStatement(expr);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(bool tint_tmp = a;
+    EXPECT_EQ(gen.Result(), R"(bool tint_tmp = a;
 if (tint_tmp) {
   tint_tmp = b;
 }
diff --git a/src/tint/writer/glsl/generator_impl_block_test.cc b/src/tint/writer/glsl/generator_impl_block_test.cc
index 1d76883..2e1485c 100644
--- a/src/tint/writer/glsl/generator_impl_block_test.cc
+++ b/src/tint/writer/glsl/generator_impl_block_test.cc
@@ -27,10 +27,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(b);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     return;
   }
 )");
diff --git a/src/tint/writer/glsl/generator_impl_break_test.cc b/src/tint/writer/glsl/generator_impl_break_test.cc
index 4912e0b..ddaad01 100644
--- a/src/tint/writer/glsl/generator_impl_break_test.cc
+++ b/src/tint/writer/glsl/generator_impl_break_test.cc
@@ -27,10 +27,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(b);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), "  break;\n");
+    EXPECT_EQ(gen.Result(), "  break;\n");
 }
 
 }  // namespace
diff --git a/src/tint/writer/glsl/generator_impl_builtin_test.cc b/src/tint/writer/glsl/generator_impl_builtin_test.cc
index 78765ef..11595a0 100644
--- a/src/tint/writer/glsl/generator_impl_builtin_test.cc
+++ b/src/tint/writer/glsl/generator_impl_builtin_test.cc
@@ -349,7 +349,7 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     utils::StringStream out;
     gen.EmitExpression(out, call);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
@@ -363,7 +363,7 @@
     WrapInFunction(Decl(Var("r", call)));
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     utils::StringStream out;
     gen.EmitExpression(out, call);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
@@ -377,7 +377,7 @@
     WrapInFunction(Decl(Var("r", call)));
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     utils::StringStream out;
     gen.EmitExpression(out, call);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
@@ -395,7 +395,7 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     utils::StringStream out;
     gen.EmitExpression(out, call);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
@@ -414,7 +414,7 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     utils::StringStream out;
     gen.EmitExpression(out, call);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
@@ -429,7 +429,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 struct modf_result_f32 {
   float fract;
@@ -466,7 +466,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 #extension GL_AMD_gpu_shader_half_float : require
 
 struct modf_result_f16 {
@@ -502,7 +502,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 struct modf_result_vec3_f32 {
   vec3 fract;
@@ -539,7 +539,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 #extension GL_AMD_gpu_shader_half_float : require
 
 struct modf_result_vec3_f16 {
@@ -574,7 +574,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 struct modf_result_f32 {
   float fract;
@@ -603,7 +603,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 #extension GL_AMD_gpu_shader_half_float : require
 
 struct modf_result_f16 {
@@ -631,7 +631,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 struct modf_result_vec3_f32 {
   vec3 fract;
@@ -660,7 +660,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 #extension GL_AMD_gpu_shader_half_float : require
 
 struct modf_result_vec3_f16 {
@@ -689,7 +689,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 struct frexp_result_f32 {
   float fract;
@@ -726,7 +726,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 #extension GL_AMD_gpu_shader_half_float : require
 
 struct frexp_result_f16 {
@@ -762,7 +762,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 struct frexp_result_vec3_f32 {
   vec3 fract;
@@ -799,7 +799,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 #extension GL_AMD_gpu_shader_half_float : require
 
 struct frexp_result_vec3_f16 {
@@ -834,7 +834,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 struct frexp_result_f32 {
   float fract;
@@ -863,7 +863,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 #extension GL_AMD_gpu_shader_half_float : require
 
 struct frexp_result_f16 {
@@ -891,7 +891,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 struct frexp_result_vec3_f32 {
   vec3 fract;
@@ -920,7 +920,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 #extension GL_AMD_gpu_shader_half_float : require
 
 struct frexp_result_vec3_f16 {
@@ -950,7 +950,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 float tint_degrees(float param_0) {
   return param_0 * 57.29577951308232286465f;
@@ -979,7 +979,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 vec3 tint_degrees(vec3 param_0) {
   return param_0 * 57.29577951308232286465f;
@@ -1010,7 +1010,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 #extension GL_AMD_gpu_shader_half_float : require
 
 float16_t tint_degrees(float16_t param_0) {
@@ -1042,7 +1042,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 #extension GL_AMD_gpu_shader_half_float : require
 
 f16vec3 tint_degrees(f16vec3 param_0) {
@@ -1072,7 +1072,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 float tint_radians(float param_0) {
   return param_0 * 0.01745329251994329547f;
@@ -1101,7 +1101,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 vec3 tint_radians(vec3 param_0) {
   return param_0 * 0.01745329251994329547f;
@@ -1132,7 +1132,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 #extension GL_AMD_gpu_shader_half_float : require
 
 float16_t tint_radians(float16_t param_0) {
@@ -1164,7 +1164,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 #extension GL_AMD_gpu_shader_half_float : require
 
 f16vec3 tint_radians(f16vec3 param_0) {
@@ -1196,7 +1196,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 uvec3 tint_extract_bits(uvec3 v, uint offset, uint count) {
   uint s = min(offset, 32u);
@@ -1231,7 +1231,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 uvec3 tint_insert_bits(uvec3 v, uvec3 n, uint offset, uint count) {
   uint s = min(offset, 32u);
@@ -1263,7 +1263,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 vec4 p1 = vec4(0.0f, 0.0f, 0.0f, 0.0f);
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -1282,7 +1282,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 vec4 p1 = vec4(0.0f, 0.0f, 0.0f, 0.0f);
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -1301,7 +1301,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 vec2 p1 = vec2(0.0f, 0.0f);
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -1320,7 +1320,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 vec2 p1 = vec2(0.0f, 0.0f);
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -1339,7 +1339,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 vec2 p1 = vec2(0.0f, 0.0f);
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -1358,7 +1358,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 uint p1 = 0u;
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -1377,7 +1377,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 uint p1 = 0u;
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -1396,7 +1396,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 uint p1 = 0u;
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -1415,7 +1415,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 uint p1 = 0u;
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -1434,7 +1434,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 uint p1 = 0u;
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -1459,7 +1459,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
 void main() {
@@ -1483,7 +1483,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
 void main() {
@@ -1501,7 +1501,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 int tint_int_dot(ivec3 a, ivec3 b) {
   return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
@@ -1528,7 +1528,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 uint tint_int_dot(uvec3 a, uvec3 b) {
   return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
@@ -1555,7 +1555,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 float tint_quantizeToF16(float param_0) {
   return unpackHalf2x16(packHalf2x16(vec2(param_0))).x;
@@ -1583,7 +1583,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 vec2 tint_quantizeToF16(vec2 param_0) {
   return unpackHalf2x16(packHalf2x16(param_0));
@@ -1611,7 +1611,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 vec3 tint_quantizeToF16(vec3 param_0) {
   return vec3(
@@ -1641,7 +1641,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 vec4 tint_quantizeToF16(vec4 param_0) {
   return vec4(
diff --git a/src/tint/writer/glsl/generator_impl_builtin_texture_test.cc b/src/tint/writer/glsl/generator_impl_builtin_texture_test.cc
index fbfb8ec..4241d92 100644
--- a/src/tint/writer/glsl/generator_impl_builtin_texture_test.cc
+++ b/src/tint/writer/glsl/generator_impl_builtin_texture_test.cc
@@ -293,8 +293,8 @@
 
     auto expected = expected_texture_overload(param.overload);
 
-    EXPECT_THAT(gen.result(), HasSubstr(expected.pre));
-    EXPECT_THAT(gen.result(), HasSubstr(expected.out));
+    EXPECT_THAT(gen.Result(), HasSubstr(expected.pre));
+    EXPECT_THAT(gen.Result(), HasSubstr(expected.out));
 }
 
 INSTANTIATE_TEST_SUITE_P(GlslGeneratorBuiltinTextureTest,
diff --git a/src/tint/writer/glsl/generator_impl_call_test.cc b/src/tint/writer/glsl/generator_impl_call_test.cc
index b14cc9a..cb93aac 100644
--- a/src/tint/writer/glsl/generator_impl_call_test.cc
+++ b/src/tint/writer/glsl/generator_impl_call_test.cc
@@ -75,10 +75,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(call);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), "  my_func(param1, param2);\n");
+    EXPECT_EQ(gen.Result(), "  my_func(param1, param2);\n");
 }
 
 }  // namespace
diff --git a/src/tint/writer/glsl/generator_impl_case_test.cc b/src/tint/writer/glsl/generator_impl_case_test.cc
index 3707f6b..5fe5b60 100644
--- a/src/tint/writer/glsl/generator_impl_case_test.cc
+++ b/src/tint/writer/glsl/generator_impl_case_test.cc
@@ -30,9 +30,9 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitCase(s->body[0]);
-    EXPECT_EQ(gen.result(), R"(  case 5: {
+    EXPECT_EQ(gen.Result(), R"(  case 5: {
     break;
   }
 )");
@@ -44,10 +44,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitCase(s->body[0]);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  case 5: {
+    EXPECT_EQ(gen.Result(), R"(  case 5: {
     break;
   }
 )");
@@ -66,10 +66,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitCase(s->body[0]);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  case 5:
+    EXPECT_EQ(gen.Result(), R"(  case 5:
   case 6: {
     break;
   }
@@ -82,10 +82,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitCase(s->body[0]);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  default: {
+    EXPECT_EQ(gen.Result(), R"(  default: {
     break;
   }
 )");
diff --git a/src/tint/writer/glsl/generator_impl_constructor_test.cc b/src/tint/writer/glsl/generator_impl_constructor_test.cc
index 8a18dc7..5bb9642 100644
--- a/src/tint/writer/glsl/generator_impl_constructor_test.cc
+++ b/src/tint/writer/glsl/generator_impl_constructor_test.cc
@@ -30,7 +30,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("false"));
+    EXPECT_THAT(gen.Result(), HasSubstr("false"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Int) {
@@ -39,7 +39,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("-12345"));
+    EXPECT_THAT(gen.Result(), HasSubstr("-12345"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, UInt) {
@@ -48,7 +48,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("56779u"));
+    EXPECT_THAT(gen.Result(), HasSubstr("56779u"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Float) {
@@ -58,7 +58,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("1073741824.0f"));
+    EXPECT_THAT(gen.Result(), HasSubstr("1073741824.0f"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, F16) {
@@ -70,7 +70,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("32752.0hf"));
+    EXPECT_THAT(gen.Result(), HasSubstr("32752.0hf"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Type_Float) {
@@ -79,7 +79,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("-0.00001200000042445026f"));
+    EXPECT_THAT(gen.Result(), HasSubstr("-0.00001200000042445026f"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Type_F16) {
@@ -90,7 +90,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("-0.0011997222900390625hf"));
+    EXPECT_THAT(gen.Result(), HasSubstr("-0.0011997222900390625hf"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Type_Bool) {
@@ -99,7 +99,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("true"));
+    EXPECT_THAT(gen.Result(), HasSubstr("true"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Type_Int) {
@@ -108,7 +108,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("-12345"));
+    EXPECT_THAT(gen.Result(), HasSubstr("-12345"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Type_Uint) {
@@ -117,7 +117,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("12345u"));
+    EXPECT_THAT(gen.Result(), HasSubstr("12345u"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Type_Vec_F32) {
@@ -126,7 +126,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("vec3(1.0f, 2.0f, 3.0f)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("vec3(1.0f, 2.0f, 3.0f)"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Type_Vec_F16) {
@@ -137,7 +137,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("f16vec3(1.0hf, 2.0hf, 3.0hf)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("f16vec3(1.0hf, 2.0hf, 3.0hf)"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Type_Vec_Empty_F32) {
@@ -146,7 +146,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("vec3(0.0f)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("vec3(0.0f)"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Type_Vec_Empty_F16) {
@@ -157,7 +157,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("f16vec3(0.0hf)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("f16vec3(0.0hf)"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_F32_Literal) {
@@ -166,7 +166,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("vec3(2.0f)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("vec3(2.0f)"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_F16_Literal) {
@@ -177,7 +177,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("f16vec3(2.0hf)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("f16vec3(2.0hf)"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_F32_Var) {
@@ -188,7 +188,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr(R"(float v = 2.0f;
+    EXPECT_THAT(gen.Result(), HasSubstr(R"(float v = 2.0f;
   vec3 tint_symbol = vec3(v);)"));
 }
 
@@ -202,7 +202,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr(R"(float16_t v = 2.0hf;
+    EXPECT_THAT(gen.Result(), HasSubstr(R"(float16_t v = 2.0hf;
   f16vec3 tint_symbol = f16vec3(v);)"));
 }
 
@@ -212,7 +212,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("bvec3(true)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("bvec3(true)"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_Int) {
@@ -221,7 +221,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("ivec3(2)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("ivec3(2)"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_UInt) {
@@ -230,7 +230,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("uvec3(2u)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("uvec3(2u)"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Type_Mat_F32) {
@@ -240,7 +240,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("mat2x3(vec3(1.0f, 2.0f, 3.0f), vec3(3.0f, 4.0f, 5.0f))"));
+    EXPECT_THAT(gen.Result(), HasSubstr("mat2x3(vec3(1.0f, 2.0f, 3.0f), vec3(3.0f, 4.0f, 5.0f))"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Type_Mat_F16) {
@@ -252,7 +252,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(),
+    EXPECT_THAT(gen.Result(),
                 HasSubstr("f16mat2x3(f16vec3(1.0hf, 2.0hf, 3.0hf), f16vec3(3.0hf, 4.0hf, 5.0hf))"));
 }
 
@@ -278,7 +278,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("mat4(vec4(2.0f, 3.0f, 4.0f, 8.0f), vec4(0.0f), "
+    EXPECT_THAT(gen.Result(), HasSubstr("mat4(vec4(2.0f, 3.0f, 4.0f, 8.0f), vec4(0.0f), "
                                         "vec4(7.0f), vec4(42.0f, 21.0f, 6.0f, -5.0f))"));
 }
 
@@ -306,7 +306,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(),
+    EXPECT_THAT(gen.Result(),
                 HasSubstr("f16mat4(f16vec4(2.0hf, 3.0hf, 4.0hf, 8.0hf), f16vec4(0.0hf), "
                           "f16vec4(7.0hf), f16vec4(42.0hf, 21.0hf, 6.0hf, -5.0hf))"));
 }
@@ -317,7 +317,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("mat2x3 tint_symbol = mat2x3(vec3(0.0f), vec3(0.0f))"));
+    EXPECT_THAT(gen.Result(), HasSubstr("mat2x3 tint_symbol = mat2x3(vec3(0.0f), vec3(0.0f))"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Type_Mat_Empty_F16) {
@@ -328,7 +328,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(),
+    EXPECT_THAT(gen.Result(),
                 HasSubstr("f16mat2x3 tint_symbol = f16mat2x3(f16vec3(0.0hf), f16vec3(0.0hf))"));
 }
 
@@ -346,7 +346,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("mat4 m_2 = mat4(m_1);"));
+    EXPECT_THAT(gen.Result(), HasSubstr("mat4 m_2 = mat4(m_1);"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Type_Mat_Identity_F16) {
@@ -365,7 +365,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("f16mat4 m_2 = f16mat4(m_1);"));
+    EXPECT_THAT(gen.Result(), HasSubstr("f16mat4 m_2 = f16mat4(m_1);"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Type_Array) {
@@ -376,7 +376,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("vec3[3](vec3(1.0f, 2.0f, 3.0f), "
+    EXPECT_THAT(gen.Result(), HasSubstr("vec3[3](vec3(1.0f, 2.0f, 3.0f), "
                                         "vec3(4.0f, 5.0f, 6.0f), "
                                         "vec3(7.0f, 8.0f, 9.0f))"));
 }
@@ -387,7 +387,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("vec3[3](vec3(0.0f), vec3(0.0f), vec3(0.0f))"));
+    EXPECT_THAT(gen.Result(), HasSubstr("vec3[3](vec3(0.0f), vec3(0.0f), vec3(0.0f))"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Type_Struct) {
@@ -402,7 +402,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("S(1, 2.0f, ivec3(3, 4, 5))"));
+    EXPECT_THAT(gen.Result(), HasSubstr("S(1, 2.0f, ivec3(3, 4, 5))"));
 }
 
 TEST_F(GlslGeneratorImplTest_Constructor, Type_Struct_Empty) {
@@ -417,7 +417,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("S(0"));
+    EXPECT_THAT(gen.Result(), HasSubstr("S(0"));
 }
 
 }  // namespace
diff --git a/src/tint/writer/glsl/generator_impl_continue_test.cc b/src/tint/writer/glsl/generator_impl_continue_test.cc
index 2c4cdfb..6768cb0 100644
--- a/src/tint/writer/glsl/generator_impl_continue_test.cc
+++ b/src/tint/writer/glsl/generator_impl_continue_test.cc
@@ -27,11 +27,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(loop);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  while (true) {
+    EXPECT_EQ(gen.Result(), R"(  while (true) {
     if (false) {
       break;
     }
diff --git a/src/tint/writer/glsl/generator_impl_discard_test.cc b/src/tint/writer/glsl/generator_impl_discard_test.cc
index cb92414..30d58c2 100644
--- a/src/tint/writer/glsl/generator_impl_discard_test.cc
+++ b/src/tint/writer/glsl/generator_impl_discard_test.cc
@@ -29,10 +29,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(stmt);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), "  discard;\n");
+    EXPECT_EQ(gen.Result(), "  discard;\n");
 }
 
 }  // namespace
diff --git a/src/tint/writer/glsl/generator_impl_function_test.cc b/src/tint/writer/glsl/generator_impl_function_test.cc
index 43f8773..b170e5b 100644
--- a/src/tint/writer/glsl/generator_impl_function_test.cc
+++ b/src/tint/writer/glsl/generator_impl_function_test.cc
@@ -36,10 +36,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  #version 310 es
+    EXPECT_EQ(gen.Result(), R"(  #version 310 es
 
   void my_func() {
     return;
@@ -56,10 +56,10 @@
 
     GeneratorImpl& gen = SanitizeAndBuild();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr(R"(  void tint_symbol() {
+    EXPECT_THAT(gen.Result(), HasSubstr(R"(  void tint_symbol() {
     return;
   })"));
 }
@@ -77,10 +77,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  #version 310 es
+    EXPECT_EQ(gen.Result(), R"(  #version 310 es
 
   void my_func(float a, int b) {
     return;
@@ -98,7 +98,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 precision highp float;
 
 void func() {
@@ -117,7 +117,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr(R"(float f(inout float foo) {
+    EXPECT_THAT(gen.Result(), HasSubstr(R"(float f(inout float foo) {
   return foo;
 }
 )"));
@@ -145,7 +145,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 precision highp float;
 
 layout(location = 0) in float foo_1;
@@ -186,7 +186,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 precision highp float;
 
 float frag_main(vec4 coord) {
@@ -238,7 +238,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 precision highp float;
 
 layout(location = 1) out float col1_1;
@@ -317,7 +317,7 @@
   GeneratorImpl& gen = SanitizeAndBuild();
 
   ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-  EXPECT_EQ(gen.result(), R"(struct VertexOutput {
+  EXPECT_EQ(gen.Result(), R"(struct VertexOutput {
   float4 pos;
 };
 
@@ -377,7 +377,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 precision highp float;
 
 struct UBO {
@@ -418,7 +418,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 precision highp float;
 
 struct Uniforms {
@@ -459,7 +459,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 precision highp float;
 
 struct Data {
@@ -506,7 +506,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(#version 310 es
 precision highp float;
 
@@ -552,7 +552,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 precision highp float;
 
 struct Data {
@@ -597,7 +597,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 precision highp float;
 
 struct Data {
@@ -644,7 +644,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 precision highp float;
 
 struct S {
@@ -690,7 +690,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(#version 310 es
 precision highp float;
 
@@ -727,7 +727,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 precision highp float;
 
 void tint_symbol() {
@@ -753,7 +753,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
 void main() {
@@ -772,7 +772,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 layout(local_size_x = 2, local_size_y = 4, local_size_z = 6) in;
 void main() {
@@ -794,7 +794,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 layout(local_size_x = 2, local_size_y = 3, local_size_z = 4) in;
 void main() {
@@ -833,7 +833,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void my_func(float a[5]) {
   return;
@@ -851,7 +851,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 float[5] my_func() {
   return float[5](0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
@@ -915,7 +915,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 struct Data {
   float d;
diff --git a/src/tint/writer/glsl/generator_impl_if_test.cc b/src/tint/writer/glsl/generator_impl_if_test.cc
index 8fb302a..132d703 100644
--- a/src/tint/writer/glsl/generator_impl_if_test.cc
+++ b/src/tint/writer/glsl/generator_impl_if_test.cc
@@ -31,10 +31,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(i);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  if (cond) {
+    EXPECT_EQ(gen.Result(), R"(  if (cond) {
     return;
   }
 )");
@@ -54,10 +54,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(i);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  if (cond) {
+    EXPECT_EQ(gen.Result(), R"(  if (cond) {
     return;
   } else {
     if (else_cond) {
@@ -79,10 +79,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(i);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  if (cond) {
+    EXPECT_EQ(gen.Result(), R"(  if (cond) {
     return;
   } else {
     return;
@@ -105,10 +105,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(i);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  if (cond) {
+    EXPECT_EQ(gen.Result(), R"(  if (cond) {
     return;
   } else {
     if (else_cond) {
diff --git a/src/tint/writer/glsl/generator_impl_loop_test.cc b/src/tint/writer/glsl/generator_impl_loop_test.cc
index 714d38b..803c1b1 100644
--- a/src/tint/writer/glsl/generator_impl_loop_test.cc
+++ b/src/tint/writer/glsl/generator_impl_loop_test.cc
@@ -34,10 +34,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(l);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  while (true) {
+    EXPECT_EQ(gen.Result(), R"(  while (true) {
     break;
   }
 )");
@@ -55,10 +55,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(l);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  while (true) {
+    EXPECT_EQ(gen.Result(), R"(  while (true) {
     break;
     {
       a_statement();
@@ -79,10 +79,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(l);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  while (true) {
+    EXPECT_EQ(gen.Result(), R"(  while (true) {
     break;
     {
       a_statement();
@@ -116,10 +116,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(outer);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  while (true) {
+    EXPECT_EQ(gen.Result(), R"(  while (true) {
     while (true) {
       break;
       {
@@ -155,10 +155,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(outer);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  while (true) {
+    EXPECT_EQ(gen.Result(), R"(  while (true) {
     float lhs = 2.5f;
     float other = 0.0f;
     break;
@@ -180,10 +180,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(f);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     for(; ; ) {
       return;
     }
@@ -202,10 +202,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(f);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     for(int i = 0; ; ) {
       return;
     }
@@ -226,10 +226,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(f);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     bool tint_tmp = t;
     if (tint_tmp) {
       tint_tmp = false;
@@ -254,10 +254,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(f);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     for(; true; ) {
       a_statement();
     }
@@ -279,10 +279,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(f);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     while (true) {
       bool tint_tmp = t;
       if (tint_tmp) {
@@ -307,10 +307,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(f);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     for(; ; i = (i + 1)) {
       return;
     }
@@ -333,10 +333,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(f);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     while (true) {
       return;
       bool tint_tmp = t;
@@ -359,10 +359,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(f);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     for(int i = 0; true; i = (i + 1)) {
       return;
     }
@@ -387,10 +387,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(f);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     bool tint_tmp = t;
     if (tint_tmp) {
       tint_tmp = false;
@@ -423,10 +423,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(f);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  while(true) {
+    EXPECT_EQ(gen.Result(), R"(  while(true) {
     return;
   }
 )");
@@ -442,10 +442,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(f);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  while(true) {
+    EXPECT_EQ(gen.Result(), R"(  while(true) {
     continue;
   }
 )");
@@ -466,10 +466,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(f);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  while (true) {
+    EXPECT_EQ(gen.Result(), R"(  while (true) {
     bool tint_tmp = t;
     if (tint_tmp) {
       tint_tmp = false;
diff --git a/src/tint/writer/glsl/generator_impl_member_accessor_test.cc b/src/tint/writer/glsl/generator_impl_member_accessor_test.cc
index 7f252b1..003954a 100644
--- a/src/tint/writer/glsl/generator_impl_member_accessor_test.cc
+++ b/src/tint/writer/glsl/generator_impl_member_accessor_test.cc
@@ -121,7 +121,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 struct Data {
   float mem;
@@ -172,7 +172,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr(p.expected));
+    EXPECT_THAT(gen.Result(), HasSubstr(p.expected));
 }
 
 INSTANTIATE_TEST_SUITE_P(GlslGeneratorImplTest_MemberAccessor,
@@ -225,7 +225,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr(p.expected));
+    EXPECT_THAT(gen.Result(), HasSubstr(p.expected));
 }
 
 INSTANTIATE_TEST_SUITE_P(GlslGeneratorImplTest_MemberAccessor,
@@ -312,7 +312,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(GlslGeneratorImplTest_MemberAccessor, StorageBuffer_Load_Matrix_Single_Element) {
@@ -360,7 +360,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(GlslGeneratorImplTest_MemberAccessor,
@@ -405,7 +405,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(GlslGeneratorImplTest_MemberAccessor,
@@ -456,7 +456,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(GlslGeneratorImplTest_MemberAccessor, StorageBuffer_Store_ToArray) {
@@ -500,7 +500,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(GlslGeneratorImplTest_MemberAccessor, StorageBuffer_Load_MultiLevel) {
@@ -559,7 +559,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(GlslGeneratorImplTest_MemberAccessor, StorageBuffer_Load_MultiLevel_Swizzle) {
@@ -620,7 +620,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(GlslGeneratorImplTest_MemberAccessor,
@@ -682,7 +682,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(GlslGeneratorImplTest_MemberAccessor, StorageBuffer_Load_MultiLevel_Index) {
@@ -743,7 +743,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(GlslGeneratorImplTest_MemberAccessor, StorageBuffer_Store_MultiLevel) {
@@ -803,7 +803,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(GlslGeneratorImplTest_MemberAccessor, StorageBuffer_Store_Swizzle_SingleLetter) {
@@ -864,7 +864,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(GlslGeneratorImplTest_MemberAccessor, Swizzle_xyz) {
@@ -875,7 +875,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("my_vec.xyz"));
+    EXPECT_THAT(gen.Result(), HasSubstr("my_vec.xyz"));
 }
 
 TEST_F(GlslGeneratorImplTest_MemberAccessor, Swizzle_gbr) {
@@ -886,7 +886,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("my_vec.gbr"));
+    EXPECT_THAT(gen.Result(), HasSubstr("my_vec.gbr"));
 }
 
 }  // namespace
diff --git a/src/tint/writer/glsl/generator_impl_module_constant_test.cc b/src/tint/writer/glsl/generator_impl_module_constant_test.cc
index 9a80721..c547f81 100644
--- a/src/tint/writer/glsl/generator_impl_module_constant_test.cc
+++ b/src/tint/writer/glsl/generator_impl_module_constant_test.cc
@@ -32,7 +32,7 @@
     GeneratorImpl& gen = Build();
     gen.EmitProgramConstVariable(var);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), "const float pos[3] = float[3](1.0f, 2.0f, 3.0f);\n");
+    EXPECT_EQ(gen.Result(), "const float pos[3] = float[3](1.0f, 2.0f, 3.0f);\n");
 }
 
 TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_AInt) {
@@ -45,7 +45,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   int l = 1;
@@ -64,7 +64,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   float l = 1.0f;
@@ -83,7 +83,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   int l = 1;
@@ -102,7 +102,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   uint l = 1u;
@@ -121,7 +121,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   float l = 1.0f;
@@ -142,7 +142,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 #extension GL_AMD_gpu_shader_half_float : require
 
 void f() {
@@ -162,7 +162,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   ivec3 l = ivec3(1, 2, 3);
@@ -181,7 +181,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   vec3 l = vec3(1.0f, 2.0f, 3.0f);
@@ -200,7 +200,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   vec3 l = vec3(1.0f, 2.0f, 3.0f);
@@ -221,7 +221,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 #extension GL_AMD_gpu_shader_half_float : require
 
 void f() {
@@ -241,7 +241,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   mat2x3 l = mat2x3(vec3(1.0f, 2.0f, 3.0f), vec3(4.0f, 5.0f, 6.0f));
@@ -260,7 +260,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   mat2x3 l = mat2x3(vec3(1.0f, 2.0f, 3.0f), vec3(4.0f, 5.0f, 6.0f));
@@ -281,7 +281,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 #extension GL_AMD_gpu_shader_half_float : require
 
 void f() {
@@ -301,7 +301,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   float l[3] = float[3](1.0f, 2.0f, 3.0f);
@@ -323,7 +323,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   bvec2 l[3] = bvec2[3](bvec2(true, false), bvec2(false, true), bvec2(true));
diff --git a/src/tint/writer/glsl/generator_impl_return_test.cc b/src/tint/writer/glsl/generator_impl_return_test.cc
index d8ddc4c..c90e76e 100644
--- a/src/tint/writer/glsl/generator_impl_return_test.cc
+++ b/src/tint/writer/glsl/generator_impl_return_test.cc
@@ -28,10 +28,10 @@
     WrapInFunction(r);
 
     GeneratorImpl& gen = Build();
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(r);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), "  return;\n");
+    EXPECT_EQ(gen.Result(), "  return;\n");
 }
 
 TEST_F(GlslGeneratorImplTest_Return, Emit_ReturnWithValue) {
@@ -39,10 +39,10 @@
     Func("f", utils::Empty, ty.i32(), utils::Vector{r});
 
     GeneratorImpl& gen = Build();
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(r);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), "  return 123;\n");
+    EXPECT_EQ(gen.Result(), "  return 123;\n");
 }
 
 }  // namespace
diff --git a/src/tint/writer/glsl/generator_impl_sanitizer_test.cc b/src/tint/writer/glsl/generator_impl_sanitizer_test.cc
index ca60d36..90628eb 100644
--- a/src/tint/writer/glsl/generator_impl_sanitizer_test.cc
+++ b/src/tint/writer/glsl/generator_impl_sanitizer_test.cc
@@ -44,7 +44,7 @@
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
 
-    auto got = gen.result();
+    auto got = gen.Result();
     auto* expect = R"(#version 310 es
 precision highp float;
 
@@ -84,7 +84,7 @@
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
 
-    auto got = gen.result();
+    auto got = gen.Result();
     auto* expect = R"(#version 310 es
 precision highp float;
 
@@ -128,7 +128,7 @@
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
 
-    auto got = gen.result();
+    auto got = gen.Result();
     auto* expect = R"(#version 310 es
 precision highp float;
 
@@ -165,7 +165,7 @@
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
 
-    auto got = gen.result();
+    auto got = gen.Result();
     auto* expect = R"(#version 310 es
 precision highp float;
 
@@ -207,7 +207,7 @@
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
 
-    auto got = gen.result();
+    auto got = gen.Result();
     auto* expect = R"(#version 310 es
 precision highp float;
 
@@ -253,7 +253,7 @@
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
 
-    auto got = gen.result();
+    auto got = gen.Result();
     auto* expect = R"(#version 310 es
 precision highp float;
 
@@ -298,7 +298,7 @@
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
 
-    auto got = gen.result();
+    auto got = gen.Result();
     auto* expect = R"(#version 310 es
 precision highp float;
 
diff --git a/src/tint/writer/glsl/generator_impl_storage_buffer_test.cc b/src/tint/writer/glsl/generator_impl_storage_buffer_test.cc
index 8ebe654..fbf7a23 100644
--- a/src/tint/writer/glsl/generator_impl_storage_buffer_test.cc
+++ b/src/tint/writer/glsl/generator_impl_storage_buffer_test.cc
@@ -51,7 +51,7 @@
     // They will likely require manual padding.
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 struct Nephews {
   float huey;
@@ -74,7 +74,7 @@
     GeneratorImpl& gen = Build(Version(Version::Standard::kDesktop, 4, 4));
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 440
+    EXPECT_EQ(gen.Result(), R"(#version 440
 
 struct Nephews {
   float huey;
diff --git a/src/tint/writer/glsl/generator_impl_switch_test.cc b/src/tint/writer/glsl/generator_impl_switch_test.cc
index f5b7e1b..d69ab6f 100644
--- a/src/tint/writer/glsl/generator_impl_switch_test.cc
+++ b/src/tint/writer/glsl/generator_impl_switch_test.cc
@@ -37,10 +37,10 @@
     WrapInFunction(s);
 
     GeneratorImpl& gen = Build();
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(s);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  switch(cond) {
+    EXPECT_EQ(gen.Result(), R"(  switch(cond) {
     case 5: {
       break;
     }
@@ -63,10 +63,10 @@
     WrapInFunction(s);
 
     GeneratorImpl& gen = Build();
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(s);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  switch(cond) {
+    EXPECT_EQ(gen.Result(), R"(  switch(cond) {
     case 5:
     default: {
       break;
diff --git a/src/tint/writer/glsl/generator_impl_test.cc b/src/tint/writer/glsl/generator_impl_test.cc
index a1b08b7..1ba0994 100644
--- a/src/tint/writer/glsl/generator_impl_test.cc
+++ b/src/tint/writer/glsl/generator_impl_test.cc
@@ -36,7 +36,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void my_func() {
 }
@@ -50,7 +50,7 @@
     GeneratorImpl& gen = Build(Version(Version::Standard::kDesktop, 4, 4));
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 440
+    EXPECT_EQ(gen.Result(), R"(#version 440
 
 void my_func() {
 }
@@ -73,7 +73,7 @@
     GeneratorImpl& gen = Build(Version(Version::Standard::kES, 3, 1));
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 #extension GL_OES_sample_variables : require
 
 int my_func() {
@@ -98,7 +98,7 @@
     GeneratorImpl& gen = Build(Version(Version::Standard::kDesktop, 4, 4));
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 440
+    EXPECT_EQ(gen.Result(), R"(#version 440
 
 int my_func() {
   return gl_SampleID;
diff --git a/src/tint/writer/glsl/generator_impl_type_test.cc b/src/tint/writer/glsl/generator_impl_type_test.cc
index 5cec150..893abfa 100644
--- a/src/tint/writer/glsl/generator_impl_type_test.cc
+++ b/src/tint/writer/glsl/generator_impl_type_test.cc
@@ -207,7 +207,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr(R"(struct S {
+    EXPECT_THAT(gen.Result(), HasSubstr(R"(struct S {
   int tint_symbol;
   float tint_symbol_1;
 };
@@ -333,7 +333,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr(params.result));
+    EXPECT_THAT(gen.Result(), HasSubstr(params.result));
 }
 INSTANTIATE_TEST_SUITE_P(
     GlslGeneratorImplTest_Type,
@@ -361,7 +361,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("sampler2DMS tex;"));
+    EXPECT_THAT(gen.Result(), HasSubstr("sampler2DMS tex;"));
 }
 
 enum class TextureDataType { F32, U32, I32 };
@@ -407,7 +407,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr(params.result));
+    EXPECT_THAT(gen.Result(), HasSubstr(params.result));
 }
 INSTANTIATE_TEST_SUITE_P(GlslGeneratorImplTest_Type,
                          GlslSampledTexturesTest,
@@ -544,7 +544,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr(params.result));
+    EXPECT_THAT(gen.Result(), HasSubstr(params.result));
 }
 INSTANTIATE_TEST_SUITE_P(
     GlslGeneratorImplTest_Type,
diff --git a/src/tint/writer/glsl/generator_impl_uniform_buffer_test.cc b/src/tint/writer/glsl/generator_impl_uniform_buffer_test.cc
index 2cf8c38..38acdd0 100644
--- a/src/tint/writer/glsl/generator_impl_uniform_buffer_test.cc
+++ b/src/tint/writer/glsl/generator_impl_uniform_buffer_test.cc
@@ -32,7 +32,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 struct Simple {
   float member;
@@ -52,7 +52,7 @@
     GeneratorImpl& gen = Build(Version(Version::Standard::kDesktop, 4, 4));
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 440
+    EXPECT_EQ(gen.Result(), R"(#version 440
 
 struct Simple {
   float member;
diff --git a/src/tint/writer/glsl/generator_impl_variable_decl_statement_test.cc b/src/tint/writer/glsl/generator_impl_variable_decl_statement_test.cc
index d4171c5..90f80c4 100644
--- a/src/tint/writer/glsl/generator_impl_variable_decl_statement_test.cc
+++ b/src/tint/writer/glsl/generator_impl_variable_decl_statement_test.cc
@@ -32,10 +32,10 @@
     WrapInFunction(stmt);
 
     GeneratorImpl& gen = Build();
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(stmt);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), "  float a = 0.0f;\n");
+    EXPECT_EQ(gen.Result(), "  float a = 0.0f;\n");
 }
 
 TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Let) {
@@ -44,10 +44,10 @@
     WrapInFunction(stmt);
 
     GeneratorImpl& gen = Build();
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(stmt);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), "  float a = 0.0f;\n");
+    EXPECT_EQ(gen.Result(), "  float a = 0.0f;\n");
 }
 
 TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const) {
@@ -56,10 +56,10 @@
     WrapInFunction(stmt);
 
     GeneratorImpl& gen = Build();
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(stmt);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), "");  // Not a mistake - 'const' is inlined
+    EXPECT_EQ(gen.Result(), "");  // Not a mistake - 'const' is inlined
 }
 
 TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_AInt) {
@@ -73,7 +73,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   int l = 1;
@@ -93,7 +93,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   float l = 1.0f;
@@ -113,7 +113,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   int l = 1;
@@ -133,7 +133,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   uint l = 1u;
@@ -153,7 +153,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   float l = 1.0f;
@@ -175,7 +175,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 #extension GL_AMD_gpu_shader_half_float : require
 
 void f() {
@@ -196,7 +196,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   ivec3 l = ivec3(1, 2, 3);
@@ -216,7 +216,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   vec3 l = vec3(1.0f, 2.0f, 3.0f);
@@ -236,7 +236,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   vec3 l = vec3(1.0f, 2.0f, 3.0f);
@@ -258,7 +258,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 #extension GL_AMD_gpu_shader_half_float : require
 
 void f() {
@@ -279,7 +279,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   mat2x3 l = mat2x3(vec3(1.0f, 2.0f, 3.0f), vec3(4.0f, 5.0f, 6.0f));
@@ -299,7 +299,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   mat2x3 l = mat2x3(vec3(1.0f, 2.0f, 3.0f), vec3(4.0f, 5.0f, 6.0f));
@@ -321,7 +321,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 #extension GL_AMD_gpu_shader_half_float : require
 
 void f() {
@@ -342,7 +342,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   float l[3] = float[3](1.0f, 2.0f, 3.0f);
@@ -362,7 +362,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   float l[2] = float[2](0.0f, 0.0f);
@@ -382,7 +382,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   float l[3][2] = float[3][2](float[2](0.0f, 0.0f), float[2](0.0f, 0.0f), float[2](0.0f, 0.0f));
@@ -403,7 +403,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 struct S {
   int a;
@@ -431,7 +431,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(#version 310 es
+    EXPECT_EQ(gen.Result(), R"(#version 310 es
 
 void f() {
   bvec2 l[3] = bvec2[3](bvec2(true, false), bvec2(false, true), bvec2(true));
@@ -446,10 +446,10 @@
     WrapInFunction(var, Expr("a"));
 
     GeneratorImpl& gen = Build();
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(),
+    EXPECT_THAT(gen.Result(),
                 HasSubstr("  float a[5] = float[5](0.0f, 0.0f, 0.0f, 0.0f, 0.0f);\n"));
 }
 
@@ -459,10 +459,10 @@
     WrapInFunction(Expr("a"));
 
     GeneratorImpl& gen = Build();
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("  float a = 0.0f;\n"));
+    EXPECT_THAT(gen.Result(), HasSubstr("  float a = 0.0f;\n"));
 }
 
 TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Initializer_ZeroVec_f32) {
@@ -474,7 +474,7 @@
     GeneratorImpl& gen = Build();
     gen.EmitStatement(stmt);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(vec3 a = vec3(0.0f);
+    EXPECT_EQ(gen.Result(), R"(vec3 a = vec3(0.0f);
 )");
 }
 
@@ -489,7 +489,7 @@
     GeneratorImpl& gen = Build();
     gen.EmitStatement(stmt);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(f16vec3 a = f16vec3(0.0hf);
+    EXPECT_EQ(gen.Result(), R"(f16vec3 a = f16vec3(0.0hf);
 )");
 }
 
@@ -502,7 +502,7 @@
     GeneratorImpl& gen = Build();
     gen.EmitStatement(stmt);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(mat2x3 a = mat2x3(vec3(0.0f), vec3(0.0f));
 )");
 }
@@ -518,7 +518,7 @@
     GeneratorImpl& gen = Build();
     gen.EmitStatement(stmt);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(f16mat2x3 a = f16mat2x3(f16vec3(0.0hf), f16vec3(0.0hf));
 )");
 }
diff --git a/src/tint/writer/glsl/generator_impl_workgroup_var_test.cc b/src/tint/writer/glsl/generator_impl_workgroup_var_test.cc
index 6edf313..a819de7 100644
--- a/src/tint/writer/glsl/generator_impl_workgroup_var_test.cc
+++ b/src/tint/writer/glsl/generator_impl_workgroup_var_test.cc
@@ -38,7 +38,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("shared float wg;\n"));
+    EXPECT_THAT(gen.Result(), HasSubstr("shared float wg;\n"));
 }
 
 TEST_F(GlslGeneratorImplTest_WorkgroupVar, Aliased) {
@@ -54,7 +54,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("shared float wg;\n"));
+    EXPECT_THAT(gen.Result(), HasSubstr("shared float wg;\n"));
 }
 
 }  // namespace
diff --git a/src/tint/writer/hlsl/generator.cc b/src/tint/writer/hlsl/generator.cc
index 17437bf..99a66fc 100644
--- a/src/tint/writer/hlsl/generator.cc
+++ b/src/tint/writer/hlsl/generator.cc
@@ -46,7 +46,7 @@
     auto impl = std::make_unique<GeneratorImpl>(&sanitized_result.program);
     result.success = impl->Generate();
     result.error = impl->Diagnostics().str();
-    result.hlsl = impl->result();
+    result.hlsl = impl->Result();
 
     // Collect the list of entry points in the sanitized program.
     for (auto* func : sanitized_result.program.AST().Functions()) {
diff --git a/src/tint/writer/hlsl/generator_impl.cc b/src/tint/writer/hlsl/generator_impl.cc
index d00859c..a00c31a 100644
--- a/src/tint/writer/hlsl/generator_impl.cc
+++ b/src/tint/writer/hlsl/generator_impl.cc
@@ -358,7 +358,7 @@
         auto* kind = &decl->TypeInfo();
         if (current_buffer_->lines.size() != last_padding_line) {
             if (last_kind && (last_kind != kind || decl->Is<ast::Function>())) {
-                line();
+                Line();
                 last_padding_line = current_buffer_->lines.size();
             }
         }
@@ -422,7 +422,7 @@
             fn = UniqueIdentifier("set_" + ss.str());
         }
         {
-            auto out = line(&helpers_);
+            auto out = Line(&helpers_);
             out << "void " << fn << "(inout ";
             if (!EmitTypeAndName(out, vec, builtin::AddressSpace::kUndefined,
                                  builtin::Access::kUndefined, "vec")) {
@@ -437,7 +437,7 @@
         }
         {
             ScopedIndent si(&helpers_);
-            auto out = line(&helpers_);
+            auto out = Line(&helpers_);
             switch (vec->Width()) {
                 case 2:
                     out << "vec = (idx.xx == int2(0, 1)) ? val.xx : vec;";
@@ -454,8 +454,8 @@
                     break;
             }
         }
-        line(&helpers_) << "}";
-        line(&helpers_);
+        Line(&helpers_) << "}";
+        Line(&helpers_);
         return fn;
     });
 
@@ -465,7 +465,7 @@
 
     auto* ast_access_expr = stmt->lhs->As<ast::IndexAccessorExpression>();
 
-    auto out = line();
+    auto out = Line();
     out << name << "(";
     if (!EmitExpression(out, ast_access_expr->object)) {
         return false;
@@ -496,7 +496,7 @@
             fn = UniqueIdentifier("set_vector_" + ss.str());
         }
         {
-            auto out = line(&helpers_);
+            auto out = Line(&helpers_);
             out << "void " << fn << "(inout ";
             if (!EmitTypeAndName(out, mat, builtin::AddressSpace::kUndefined,
                                  builtin::Access::kUndefined, "mat")) {
@@ -511,17 +511,17 @@
         }
         {
             ScopedIndent si(&helpers_);
-            line(&helpers_) << "switch (col) {";
+            Line(&helpers_) << "switch (col) {";
             {
                 ScopedIndent si2(&helpers_);
                 for (uint32_t i = 0; i < mat->columns(); ++i) {
-                    line(&helpers_) << "case " << i << ": mat[" << i << "] = val; break;";
+                    Line(&helpers_) << "case " << i << ": mat[" << i << "] = val; break;";
                 }
             }
-            line(&helpers_) << "}";
+            Line(&helpers_) << "}";
         }
-        line(&helpers_) << "}";
-        line(&helpers_);
+        Line(&helpers_) << "}";
+        Line(&helpers_);
         return fn;
     });
 
@@ -531,7 +531,7 @@
 
     auto* ast_access_expr = stmt->lhs->As<ast::IndexAccessorExpression>();
 
-    auto out = line();
+    auto out = Line();
     out << name << "(";
     if (!EmitExpression(out, ast_access_expr->object)) {
         return false;
@@ -565,7 +565,7 @@
             fn = UniqueIdentifier("set_scalar_" + ss.str());
         }
         {
-            auto out = line(&helpers_);
+            auto out = Line(&helpers_);
             out << "void " << fn << "(inout ";
             if (!EmitTypeAndName(out, mat, builtin::AddressSpace::kUndefined,
                                  builtin::Access::kUndefined, "mat")) {
@@ -580,16 +580,16 @@
         }
         {
             ScopedIndent si(&helpers_);
-            line(&helpers_) << "switch (col) {";
+            Line(&helpers_) << "switch (col) {";
             {
                 ScopedIndent si2(&helpers_);
                 for (uint32_t i = 0; i < mat->columns(); ++i) {
-                    line(&helpers_) << "case " << i << ":";
+                    Line(&helpers_) << "case " << i << ":";
                     {
                         auto vec_name = "mat[" + std::to_string(i) + "]";
                         ScopedIndent si3(&helpers_);
                         {
-                            auto out = line(&helpers_);
+                            auto out = Line(&helpers_);
                             switch (mat->rows()) {
                                 case 2:
                                     out << vec_name
@@ -616,14 +616,14 @@
                                 }
                             }
                         }
-                        line(&helpers_) << "break;";
+                        Line(&helpers_) << "break;";
                     }
                 }
             }
-            line(&helpers_) << "}";
+            Line(&helpers_) << "}";
         }
-        line(&helpers_) << "}";
-        line(&helpers_);
+        Line(&helpers_) << "}";
+        Line(&helpers_);
         return fn;
     });
 
@@ -631,7 +631,7 @@
         return false;
     }
 
-    auto out = line();
+    auto out = Line();
     out << name << "(";
     if (!EmitExpression(out, lhs_col_access->object)) {
         return false;
@@ -724,7 +724,7 @@
         }
     }
 
-    auto out = line();
+    auto out = Line();
     if (!EmitExpression(out, stmt->lhs)) {
         return false;
     }
@@ -741,7 +741,7 @@
         auto name = UniqueIdentifier(kTempNamePrefix);
 
         {
-            auto pre = line();
+            auto pre = Line();
             pre << "bool " << name << " = ";
             if (!EmitExpression(pre, expr->lhs)) {
                 return false;
@@ -750,14 +750,14 @@
         }
 
         if (expr->op == ast::BinaryOp::kLogicalOr) {
-            line() << "if (!" << name << ") {";
+            Line() << "if (!" << name << ") {";
         } else {
-            line() << "if (" << name << ") {";
+            Line() << "if (" << name << ") {";
         }
 
         {
             ScopedIndent si(this);
-            auto pre = line();
+            auto pre = Line();
             pre << name << " = ";
             if (!EmitExpression(pre, expr->rhs)) {
                 return false;
@@ -765,7 +765,7 @@
             pre << ";";
         }
 
-        line() << "}";
+        Line() << "}";
 
         out << "(" << name << ")";
         return true;
@@ -888,21 +888,21 @@
 }
 
 bool GeneratorImpl::EmitBlock(const ast::BlockStatement* stmt) {
-    line() << "{";
+    Line() << "{";
     if (!EmitStatementsWithIndent(stmt->statements)) {
         return false;
     }
-    line() << "}";
+    Line() << "}";
     return true;
 }
 
 bool GeneratorImpl::EmitBreak(const ast::BreakStatement*) {
-    line() << "break;";
+    Line() << "break;";
     return true;
 }
 
 bool GeneratorImpl::EmitBreakIf(const ast::BreakIfStatement* b) {
-    auto out = line();
+    auto out = Line();
     out << "if (";
     if (!EmitExpression(out, b->condition)) {
         return false;
@@ -1191,18 +1191,18 @@
             scalar_offset_bytes_expr = UniqueIdentifier("scalar_offset_bytes");
             scalar_offset_index_expr = UniqueIdentifier("scalar_offset_index");
             {
-                auto pre = line();
+                auto pre = Line();
                 pre << "const uint " << scalar_offset_bytes_expr << " = (";
                 if (!EmitExpression(pre, offset)) {
                     return false;
                 }
                 pre << ");";
             }
-            line() << "const uint " << scalar_offset_index_expr << " = " << scalar_offset_bytes_expr
+            Line() << "const uint " << scalar_offset_index_expr << " = " << scalar_offset_bytes_expr
                    << " / 4;";
         } else {
             scalar_offset_index_unified_expr = UniqueIdentifier("scalar_offset");
-            auto pre = line();
+            auto pre = Line();
             pre << "const uint " << scalar_offset_index_unified_expr << " = (";
             if (!EmitExpression(pre, offset)) {
                 return false;
@@ -1243,7 +1243,7 @@
                 } else {
                     std::string ubo_load = UniqueIdentifier("ubo_load");
                     {
-                        auto pre = line();
+                        auto pre = Line();
                         pre << "uint4 " << ubo_load << " = " << buffer << "["
                             << scalar_offset_index_unified_expr << " / 4];";
                     }
@@ -1301,7 +1301,7 @@
                 //     float16_t(f16tof32(ubo_load >> 16)))
                 std::string ubo_load = UniqueIdentifier("ubo_load");
                 {
-                    auto pre = line();
+                    auto pre = Line();
                     // Load the 4 bytes f16 vector as an uint
                     pre << "uint " << ubo_load << " = ";
                     if (!load_u32_to(pre)) {
@@ -1329,7 +1329,7 @@
                 std::string ubo_load_xz = UniqueIdentifier(ubo_load + "_xz");
                 std::string ubo_load_y = UniqueIdentifier(ubo_load + "_y");
                 {
-                    auto pre = line();
+                    auto pre = Line();
                     // Load the 8 bytes uint2 with the f16 vector at lower 6 bytes
                     pre << "uint2 " << ubo_load << " = ";
                     if (!load_vec2_u32_to(pre)) {
@@ -1338,12 +1338,12 @@
                     pre << ";";
                 }
                 {
-                    auto pre = line();
+                    auto pre = Line();
                     pre << "vector<float16_t, 2> " << ubo_load_xz
                         << " = vector<float16_t, 2>(f16tof32(" << ubo_load << " & 0xFFFF));";
                 }
                 {
-                    auto pre = line();
+                    auto pre = Line();
                     pre << "float16_t " << ubo_load_y << " = f16tof32(" << ubo_load
                         << "[0] >> 16);";
                 }
@@ -1369,7 +1369,7 @@
                 std::string ubo_load_xz = UniqueIdentifier(ubo_load + "_xz");
                 std::string ubo_load_yw = UniqueIdentifier(ubo_load + "_yw");
                 {
-                    auto pre = line();
+                    auto pre = Line();
                     // Load the 8 bytes f16 vector as an uint2
                     pre << "uint2 " << ubo_load << " = ";
                     if (!load_vec2_u32_to(pre)) {
@@ -1378,12 +1378,12 @@
                     pre << ";";
                 }
                 {
-                    auto pre = line();
+                    auto pre = Line();
                     pre << "vector<float16_t, 2> " << ubo_load_xz
                         << " = vector<float16_t, 2>(f16tof32(" << ubo_load << " & 0xFFFF));";
                 }
                 {
-                    auto pre = line();
+                    auto pre = Line();
                     pre << "vector<float16_t, 2> " << ubo_load_yw
                         << " = vector<float16_t, 2>(f16tof32(" << ubo_load << " >> 16));";
                 }
@@ -1614,7 +1614,7 @@
 
     auto rmw = [&](const char* hlsl) -> bool {
         {
-            auto fn = line(&buf);
+            auto fn = Line(&buf);
             if (!EmitTypeAndName(fn, result_ty, builtin::AddressSpace::kUndefined,
                                  builtin::Access::kUndefined, name)) {
                 return false;
@@ -1630,12 +1630,12 @@
         buf.IncrementIndent();
         TINT_DEFER({
             buf.DecrementIndent();
-            line(&buf) << "}";
-            line(&buf);
+            Line(&buf) << "}";
+            Line(&buf);
         });
 
         {
-            auto l = line(&buf);
+            auto l = Line(&buf);
             if (!EmitTypeAndName(l, result_ty, builtin::AddressSpace::kUndefined,
                                  builtin::Access::kUndefined, "original_value")) {
                 return false;
@@ -1643,14 +1643,14 @@
             l << " = 0;";
         }
         {
-            auto l = line(&buf);
+            auto l = Line(&buf);
             l << buffer << "." << hlsl << "(offset, ";
             if (intrinsic->op == Op::kAtomicSub) {
                 l << "-";
             }
             l << "value, original_value);";
         }
-        line(&buf) << "return original_value;";
+        Line(&buf) << "return original_value;";
         return true;
     };
 
@@ -1684,7 +1684,7 @@
             // HLSL does not have an InterlockedLoad, so we emulate it with
             // InterlockedOr using 0 as the OR value
             {
-                auto fn = line(&buf);
+                auto fn = Line(&buf);
                 if (!EmitTypeAndName(fn, result_ty, builtin::AddressSpace::kUndefined,
                                      builtin::Access::kUndefined, name)) {
                     return false;
@@ -1695,12 +1695,12 @@
             buf.IncrementIndent();
             TINT_DEFER({
                 buf.DecrementIndent();
-                line(&buf) << "}";
-                line(&buf);
+                Line(&buf) << "}";
+                Line(&buf);
             });
 
             {
-                auto l = line(&buf);
+                auto l = Line(&buf);
                 if (!EmitTypeAndName(l, result_ty, builtin::AddressSpace::kUndefined,
                                      builtin::Access::kUndefined, "value")) {
                     return false;
@@ -1708,8 +1708,8 @@
                 l << " = 0;";
             }
 
-            line(&buf) << buffer << ".InterlockedOr(offset, 0, value);";
-            line(&buf) << "return value;";
+            Line(&buf) << buffer << ".InterlockedOr(offset, 0, value);";
+            Line(&buf) << "return value;";
             return true;
         }
         case Op::kAtomicStore: {
@@ -1717,7 +1717,7 @@
             // HLSL does not have an InterlockedStore, so we emulate it with
             // InterlockedExchange and discard the returned value
             {
-                auto fn = line(&buf);
+                auto fn = Line(&buf);
                 fn << "void " << name << "(uint offset, ";
                 if (!EmitTypeAndName(fn, value_ty, builtin::AddressSpace::kUndefined,
                                      builtin::Access::kUndefined, "value")) {
@@ -1729,19 +1729,19 @@
             buf.IncrementIndent();
             TINT_DEFER({
                 buf.DecrementIndent();
-                line(&buf) << "}";
-                line(&buf);
+                Line(&buf) << "}";
+                Line(&buf);
             });
 
             {
-                auto l = line(&buf);
+                auto l = Line(&buf);
                 if (!EmitTypeAndName(l, value_ty, builtin::AddressSpace::kUndefined,
                                      builtin::Access::kUndefined, "ignored")) {
                     return false;
                 }
                 l << ";";
             }
-            line(&buf) << buffer << ".InterlockedExchange(offset, value, ignored);";
+            Line(&buf) << buffer << ".InterlockedExchange(offset, value, ignored);";
             return true;
         }
         case Op::kAtomicCompareExchangeWeak: {
@@ -1753,7 +1753,7 @@
             // NOTE: We don't need to emit the return type struct here as DecomposeMemoryAccess
             // already added it to the AST, and it should have already been emitted by now.
             {
-                auto fn = line(&buf);
+                auto fn = Line(&buf);
                 if (!EmitTypeAndName(fn, result_ty, builtin::AddressSpace::kUndefined,
                                      builtin::Access::kUndefined, name)) {
                     return false;
@@ -1774,12 +1774,12 @@
             buf.IncrementIndent();
             TINT_DEFER({
                 buf.DecrementIndent();
-                line(&buf) << "}";
-                line(&buf);
+                Line(&buf) << "}";
+                Line(&buf);
             });
 
             {  // T result = {0};
-                auto l = line(&buf);
+                auto l = Line(&buf);
                 if (!EmitTypeAndName(l, result_ty, builtin::AddressSpace::kUndefined,
                                      builtin::Access::kUndefined, "result")) {
                     return false;
@@ -1791,10 +1791,10 @@
                 l << ";";
             }
 
-            line(&buf) << buffer
+            Line(&buf) << buffer
                        << ".InterlockedCompareExchange(offset, compare, value, result.old_value);";
-            line(&buf) << "result.exchanged = result.old_value == compare;";
-            line(&buf) << "return result;";
+            Line(&buf) << "result.exchanged = result.old_value == compare;";
+            Line(&buf) << "return result;";
 
             return true;
         }
@@ -1814,7 +1814,7 @@
     std::string result = UniqueIdentifier("atomic_result");
 
     if (!builtin->ReturnType()->Is<type::Void>()) {
-        auto pre = line();
+        auto pre = Line();
         if (!EmitTypeAndName(pre, builtin->ReturnType(), builtin::AddressSpace::kUndefined,
                              builtin::Access::kUndefined, result)) {
             return false;
@@ -1827,7 +1827,7 @@
     }
 
     auto call = [&](const char* name) {
-        auto pre = line();
+        auto pre = Line();
         pre << name;
 
         {
@@ -1859,7 +1859,7 @@
         case builtin::Function::kAtomicLoad: {
             // HLSL does not have an InterlockedLoad, so we emulate it with
             // InterlockedOr using 0 as the OR value
-            auto pre = line();
+            auto pre = Line();
             pre << "InterlockedOr";
             {
                 ScopedParen sp(pre);
@@ -1877,7 +1877,7 @@
             // HLSL does not have an InterlockedStore, so we emulate it with
             // InterlockedExchange and discard the returned value
             {  // T result = 0;
-                auto pre = line();
+                auto pre = Line();
                 auto* value_ty = builtin->Parameters()[1]->Type()->UnwrapRef();
                 if (!EmitTypeAndName(pre, value_ty, builtin::AddressSpace::kUndefined,
                                      builtin::Access::kUndefined, result)) {
@@ -1916,7 +1916,7 @@
             std::string compare = UniqueIdentifier("atomic_compare_value");
 
             {  // T compare_value = <compare_value>;
-                auto pre = line();
+                auto pre = Line();
                 if (!EmitTypeAndName(pre, TypeOf(compare_value)->UnwrapRef(),
                                      builtin::AddressSpace::kUndefined, builtin::Access::kUndefined,
                                      compare)) {
@@ -1930,7 +1930,7 @@
             }
 
             {  // InterlockedCompareExchange(dst, compare, value, result.old_value);
-                auto pre = line();
+                auto pre = Line();
                 pre << "InterlockedCompareExchange";
                 {
                     ScopedParen sp(pre);
@@ -1947,7 +1947,7 @@
             }
 
             // result.exchanged = result.old_value == compare;
-            line() << result << ".exchanged = " << result << ".old_value == " << compare << ";";
+            Line() << result << ".exchanged = " << result << ".old_value == " << compare << ";";
 
             out << result;
             return true;
@@ -2027,15 +2027,15 @@
             }
 
             {
-                auto l = line(b);
+                auto l = Line(b);
                 if (!EmitType(l, builtin->ReturnType(), builtin::AddressSpace::kUndefined,
                               builtin::Access::kUndefined, "")) {
                     return false;
                 }
                 l << " result;";
             }
-            line(b) << "result.fract = modf(" << params[0] << ", result.whole);";
-            line(b) << "return result;";
+            Line(b) << "result.fract = modf(" << params[0] << ", result.whole);";
+            Line(b) << "return result;";
             return true;
         });
 }
@@ -2066,17 +2066,17 @@
                 member_type = "float" + width;
             }
 
-            line(b) << member_type << " exp;";
-            line(b) << member_type << " fract = sign(" << in << ") * frexp(" << in << ", exp);";
+            Line(b) << member_type << " exp;";
+            Line(b) << member_type << " fract = sign(" << in << ") * frexp(" << in << ", exp);";
             {
-                auto l = line(b);
+                auto l = Line(b);
                 if (!EmitType(l, builtin->ReturnType(), builtin::AddressSpace::kUndefined,
                               builtin::Access::kUndefined, "")) {
                     return false;
                 }
                 l << " result = {fract, int" << width << "(exp)};";
             }
-            line(b) << "return result;";
+            Line(b) << "return result;";
             return true;
         });
 }
@@ -2086,7 +2086,7 @@
                                     const sem::Builtin* builtin) {
     return CallBuiltinHelper(out, expr, builtin,
                              [&](TextBuffer* b, const std::vector<std::string>& params) {
-                                 line(b) << "return " << params[0] << " * " << std::setprecision(20)
+                                 Line(b) << "return " << params[0] << " * " << std::setprecision(20)
                                          << sem::kRadToDeg << ";";
                                  return true;
                              });
@@ -2097,7 +2097,7 @@
                                     const sem::Builtin* builtin) {
     return CallBuiltinHelper(out, expr, builtin,
                              [&](TextBuffer* b, const std::vector<std::string>& params) {
-                                 line(b) << "return " << params[0] << " * " << std::setprecision(20)
+                                 Line(b) << "return " << params[0] << " * " << std::setprecision(20)
                                          << sem::kDegToRad << ";";
                                  return true;
                              });
@@ -2147,7 +2147,7 @@
     return CallBuiltinHelper(  //
         out, expr, builtin, [&](TextBuffer* b, const std::vector<std::string>& params) {
             // value < 0 ? ceil(value) : floor(value)
-            line(b) << "return " << params[0] << " < 0 ? ceil(" << params[0] << ") : floor("
+            Line(b) << "return " << params[0] << " < 0 ? ceil(" << params[0] << ") : floor("
                     << params[0] << ");";
             return true;
         });
@@ -2177,7 +2177,7 @@
                 case builtin::Function::kPack2X16Snorm:
                 case builtin::Function::kPack2X16Unorm: {
                     {
-                        auto l = line(b);
+                        auto l = Line(b);
                         l << (is_signed ? "" : "u") << "int" << dims
                           << " i = " << (is_signed ? "" : "u") << "int" << dims << "(round(clamp("
                           << params[0] << ", " << (is_signed ? "-1.0" : "0.0") << ", 1.0) * "
@@ -2188,7 +2188,7 @@
                         l << ";";
                     }
                     {
-                        auto l = line(b);
+                        auto l = Line(b);
                         l << "return ";
                         if (is_signed) {
                             l << "asuint";
@@ -2202,8 +2202,8 @@
                     break;
                 }
                 case builtin::Function::kPack2X16Float: {
-                    line(b) << "uint2 i = f32tof16(" << params[0] << ");";
-                    line(b) << "return i.x | (i.y << 16);";
+                    Line(b) << "uint2 i = f32tof16(" << params[0] << ");";
+                    Line(b) << "return i.x | (i.y << 16);";
                     break;
                 }
                 default:
@@ -2237,9 +2237,9 @@
             switch (builtin->Type()) {
                 case builtin::Function::kUnpack4X8Snorm:
                 case builtin::Function::kUnpack2X16Snorm: {
-                    line(b) << "int j = int(" << params[0] << ");";
+                    Line(b) << "int j = int(" << params[0] << ");";
                     {  // Perform sign extension on the converted values.
-                        auto l = line(b);
+                        auto l = Line(b);
                         l << "int" << dims << " i = int" << dims << "(";
                         if (dims == 2) {
                             l << "j << 16, j) >> 16";
@@ -2248,15 +2248,15 @@
                         }
                         l << ";";
                     }
-                    line(b) << "return clamp(float" << dims << "(i) / " << scale << ".0, "
+                    Line(b) << "return clamp(float" << dims << "(i) / " << scale << ".0, "
                             << (is_signed ? "-1.0" : "0.0") << ", 1.0);";
                     break;
                 }
                 case builtin::Function::kUnpack4X8Unorm:
                 case builtin::Function::kUnpack2X16Unorm: {
-                    line(b) << "uint j = " << params[0] << ";";
+                    Line(b) << "uint j = " << params[0] << ";";
                     {
-                        auto l = line(b);
+                        auto l = Line(b);
                         l << "uint" << dims << " i = uint" << dims << "(";
                         l << "j & " << (dims == 2 ? "0xffff" : "0xff") << ", ";
                         if (dims == 4) {
@@ -2266,12 +2266,12 @@
                         }
                         l << ");";
                     }
-                    line(b) << "return float" << dims << "(i) / " << scale << ".0;";
+                    Line(b) << "return float" << dims << "(i) / " << scale << ".0;";
                     break;
                 }
                 case builtin::Function::kUnpack2X16Float:
-                    line(b) << "uint i = " << params[0] << ";";
-                    line(b) << "return f16tof32(uint2(i & 0xffff, i >> 16));";
+                    Line(b) << "uint i = " << params[0] << ";";
+                    Line(b) << "return f16tof32(uint2(i & 0xffff, i >> 16));";
                     break;
                 default:
                     diagnostics_.add_error(diag::System::Writer,
@@ -2292,11 +2292,11 @@
             std::string functionName;
             switch (builtin->Type()) {
                 case builtin::Function::kDot4I8Packed:
-                    line(b) << "int accumulator = 0;";
+                    Line(b) << "int accumulator = 0;";
                     functionName = "dot4add_i8packed";
                     break;
                 case builtin::Function::kDot4U8Packed:
-                    line(b) << "uint accumulator = 0u;";
+                    Line(b) << "uint accumulator = 0u;";
                     functionName = "dot4add_u8packed";
                     break;
                 default:
@@ -2304,7 +2304,7 @@
                                            "Internal error: unhandled DP4a builtin");
                     return false;
             }
-            line(b) << "return " << functionName << "(" << params[0] << ", " << params[1]
+            Line(b) << "return " << functionName << "(" << params[0] << ", " << params[1]
                     << ", accumulator);";
 
             return true;
@@ -2474,13 +2474,13 @@
             // Declare a variable to hold the queried texture info
             auto dims = UniqueIdentifier(kTempNamePrefix);
             if (num_dimensions == 1) {
-                line() << "uint " << dims << ";";
+                Line() << "uint " << dims << ";";
             } else {
-                line() << "uint" << num_dimensions << " " << dims << ";";
+                Line() << "uint" << num_dimensions << " " << dims << ";";
             }
 
             {  // texture.GetDimensions(...)
-                auto pre = line();
+                auto pre = Line();
                 if (!EmitExpression(pre, texture)) {
                     return false;
                 }
@@ -2786,7 +2786,7 @@
     auto* stmt = s->body[case_idx];
     auto* sem = builder_.Sem().Get<sem::CaseStatement>(stmt);
     for (auto* selector : sem->Selectors()) {
-        auto out = line();
+        auto out = Line();
         if (selector->IsDefault()) {
             out << "default";
         } else {
@@ -2801,10 +2801,10 @@
         }
     }
 
-    increment_indent();
+    IncrementIndent();
     TINT_DEFER({
-        decrement_indent();
-        line() << "}";
+        DecrementIndent();
+        Line() << "}";
     });
 
     // Emit the case statement
@@ -2813,7 +2813,7 @@
     }
 
     if (!tint::utils::IsAnyOf<ast::BreakStatement>(stmt->body->Last())) {
-        line() << "break;";
+        Line() << "break;";
     }
 
     return true;
@@ -2823,14 +2823,14 @@
     if (!emit_continuing_ || !emit_continuing_()) {
         return false;
     }
-    line() << "continue;";
+    Line() << "continue;";
     return true;
 }
 
 bool GeneratorImpl::EmitDiscard(const ast::DiscardStatement*) {
     // TODO(dsinclair): Verify this is correct when the discard semantics are
     // defined for WGSL (https://github.com/gpuweb/gpuweb/issues/361)
-    line() << "discard;";
+    Line() << "discard;";
     return true;
 }
 
@@ -2871,7 +2871,7 @@
 
 bool GeneratorImpl::EmitIf(const ast::IfStatement* stmt) {
     {
-        auto out = line();
+        auto out = Line();
         out << "if (";
         if (!EmitExpression(out, stmt->condition)) {
             return false;
@@ -2884,7 +2884,7 @@
     }
 
     if (stmt->else_statement) {
-        line() << "} else {";
+        Line() << "} else {";
         if (auto* block = stmt->else_statement->As<ast::BlockStatement>()) {
             if (!EmitStatementsWithIndent(block->statements)) {
                 return false;
@@ -2895,7 +2895,7 @@
             }
         }
     }
-    line() << "}";
+    Line() << "}";
 
     return true;
 }
@@ -2920,13 +2920,13 @@
     }
 
     {
-        auto out = line();
+        auto out = Line();
         auto name = func->name->symbol.Name();
         // If the function returns an array, then we need to declare a typedef for
         // this.
         if (sem->ReturnType()->Is<type::Array>()) {
             auto typedef_name = UniqueIdentifier(name + "_ret");
-            auto pre = line();
+            auto pre = Line();
             pre << "typedef ";
             if (!EmitTypeAndName(pre, sem->ReturnType(), builtin::AddressSpace::kUndefined,
                                  builtin::Access::kReadWrite, typedef_name)) {
@@ -2999,7 +2999,7 @@
         }
     }
 
-    line() << "}";
+    Line() << "}";
 
     return true;
 }
@@ -3014,25 +3014,25 @@
     TINT_ASSERT(Writer, sem->DiscardStatement() && !sem->ReturnType()->Is<type::Void>());
 
     ScopedIndent si(this);
-    line() << "if (true) {";
+    Line() << "if (true) {";
 
     if (!EmitStatementsWithIndent(func->body->statements)) {
         return false;
     }
 
-    line() << "}";
+    Line() << "}";
 
     // Return an unused result that matches the type of the return value
     auto name = builder_.Symbols().New("unused").Name();
     {
-        auto out = line();
+        auto out = Line();
         if (!EmitTypeAndName(out, sem->ReturnType(), builtin::AddressSpace::kUndefined,
                              builtin::Access::kReadWrite, name)) {
             return false;
         }
         out << ";";
     }
-    line() << "return " << name << ";";
+    Line() << "return " << name << ";";
 
     return true;
 }
@@ -3087,25 +3087,25 @@
     auto binding_point = *sem->As<sem::GlobalVariable>()->BindingPoint();
     auto* type = sem->Type()->UnwrapRef();
     auto name = var->name->symbol.Name();
-    line() << "cbuffer cbuffer_" << name << RegisterAndSpace('b', binding_point) << " {";
+    Line() << "cbuffer cbuffer_" << name << RegisterAndSpace('b', binding_point) << " {";
 
     {
         ScopedIndent si(this);
-        auto out = line();
+        auto out = Line();
         if (!EmitTypeAndName(out, type, builtin::AddressSpace::kUniform, sem->Access(), name)) {
             return false;
         }
         out << ";";
     }
 
-    line() << "};";
+    Line() << "};";
 
     return true;
 }
 
 bool GeneratorImpl::EmitStorageVariable(const ast::Var* var, const sem::Variable* sem) {
     auto* type = sem->Type()->UnwrapRef();
-    auto out = line();
+    auto out = Line();
     if (!EmitTypeAndName(out, type, builtin::AddressSpace::kStorage, sem->Access(),
                          var->name->symbol.Name())) {
         return false;
@@ -3121,7 +3121,7 @@
 
 bool GeneratorImpl::EmitHandleVariable(const ast::Var* var, const sem::Variable* sem) {
     auto* unwrapped_type = sem->Type()->UnwrapRef();
-    auto out = line();
+    auto out = Line();
 
     auto name = var->name->symbol.Name();
     auto* type = sem->Type()->UnwrapRef();
@@ -3159,7 +3159,7 @@
 
 bool GeneratorImpl::EmitPrivateVariable(const sem::Variable* var) {
     auto* decl = var->Declaration();
-    auto out = line();
+    auto out = Line();
 
     out << "static ";
 
@@ -3186,7 +3186,7 @@
 
 bool GeneratorImpl::EmitWorkgroupVariable(const sem::Variable* var) {
     auto* decl = var->Declaration();
-    auto out = line();
+    auto out = Line();
 
     out << "groupshared ";
 
@@ -3272,7 +3272,7 @@
     auto* func_sem = builder_.Sem().Get(func);
 
     {
-        auto out = line();
+        auto out = Line();
         if (func->PipelineStage() == ast::PipelineStage::kCompute) {
             // Emit the workgroup_size attribute.
             auto wgsize = func_sem->WorkgroupSize();
@@ -3340,7 +3340,7 @@
         }
     }
 
-    line() << "}";
+    Line() << "}";
 
     return true;
 }
@@ -3487,7 +3487,7 @@
                 // HLSL requires structure initializers to be assigned directly to a variable.
                 auto name = UniqueIdentifier("c");
                 {
-                    auto decl = line();
+                    auto decl = Line();
                     decl << "const " << StructName(s) << " " << name << " = ";
                     if (!emit_member_values(decl)) {
                         return false;
@@ -3631,7 +3631,7 @@
     };
 
     TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
-    line() << "while (true) {";
+    Line() << "while (true) {";
     {
         ScopedIndent si(this);
         if (!EmitStatements(stmt->body->statements)) {
@@ -3641,7 +3641,7 @@
             return false;
         }
     }
-    line() << "}";
+    Line() << "}";
 
     return true;
 }
@@ -3649,11 +3649,11 @@
 bool GeneratorImpl::EmitForLoop(const ast::ForLoopStatement* stmt) {
     // Nest a for loop with a new block. In HLSL the initializer scope is not
     // nested by the for-loop, so we may get variable redefinitions.
-    line() << "{";
-    increment_indent();
+    Line() << "{";
+    IncrementIndent();
     TINT_DEFER({
-        decrement_indent();
-        line() << "}";
+        DecrementIndent();
+        Line() << "}";
     });
 
     TextBuffer init_buf;
@@ -3701,16 +3701,16 @@
         };
 
         TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
-        line() << "while (true) {";
-        increment_indent();
+        Line() << "while (true) {";
+        IncrementIndent();
         TINT_DEFER({
-            decrement_indent();
-            line() << "}";
+            DecrementIndent();
+            Line() << "}";
         });
 
         if (stmt->condition) {
             current_buffer_->Append(cond_pre);
-            line() << "if (!(" << cond_buf.str() << ")) { break; }";
+            Line() << "if (!(" << cond_buf.str() << ")) { break; }";
         }
 
         if (!EmitStatements(stmt->body->statements)) {
@@ -3723,7 +3723,7 @@
     } else {
         // For-loop can be generated.
         {
-            auto out = line();
+            auto out = Line();
             out << "for";
             {
                 ScopedParen sp(out);
@@ -3749,7 +3749,7 @@
                 return false;
             }
         }
-        line() << "}";
+        Line() << "}";
     }
 
     return true;
@@ -3773,22 +3773,22 @@
     // as a regular while in HLSL. Instead we need to generate a `while(true)` loop.
     bool emit_as_loop = cond_pre.lines.size() > 0;
     if (emit_as_loop) {
-        line() << "while (true) {";
-        increment_indent();
+        Line() << "while (true) {";
+        IncrementIndent();
         TINT_DEFER({
-            decrement_indent();
-            line() << "}";
+            DecrementIndent();
+            Line() << "}";
         });
 
         current_buffer_->Append(cond_pre);
-        line() << "if (!(" << cond_buf.str() << ")) { break; }";
+        Line() << "if (!(" << cond_buf.str() << ")) { break; }";
         if (!EmitStatements(stmt->body->statements)) {
             return false;
         }
     } else {
         // While can be generated.
         {
-            auto out = line();
+            auto out = Line();
             out << "while";
             {
                 ScopedParen sp(out);
@@ -3799,7 +3799,7 @@
         if (!EmitStatementsWithIndent(stmt->body->statements)) {
             return false;
         }
-        line() << "}";
+        Line() << "}";
     }
 
     return true;
@@ -3834,14 +3834,14 @@
 
 bool GeneratorImpl::EmitReturn(const ast::ReturnStatement* stmt) {
     if (stmt->value) {
-        auto out = line();
+        auto out = Line();
         out << "return ";
         if (!EmitExpression(out, stmt->value)) {
             return false;
         }
         out << ";";
     } else {
-        line() << "return;";
+        Line() << "return;";
     }
     return true;
 }
@@ -3862,7 +3862,7 @@
             return EmitBreakIf(b);
         },
         [&](const ast::CallStatement* c) {  //
-            auto out = line();
+            auto out = Line();
             if (!EmitCall(out, c->expr)) {
                 return false;
             }
@@ -3927,7 +3927,7 @@
     // Emit the switch condition as-is if it has side-effects (e.g.
     // function call). Note that we can ignore the result of the expression (if any).
     if (auto* sem_cond = builder_.Sem().GetVal(stmt->condition); sem_cond->HasSideEffects()) {
-        auto out = line();
+        auto out = Line();
         if (!EmitExpression(out, stmt->condition)) {
             return false;
         }
@@ -3937,14 +3937,14 @@
     // Emit "do { <default case body> } while(false);". We use a 'do' loop so
     // that break statements work as expected, and make it 'while (false)' in
     // case there isn't a break statement.
-    line() << "do {";
+    Line() << "do {";
     {
         ScopedIndent si(this);
         if (!EmitStatements(stmt->body[0]->body->statements)) {
             return false;
         }
     }
-    line() << "} while (false);";
+    Line() << "} while (false);";
     return true;
 }
 
@@ -3956,7 +3956,7 @@
     }
 
     {  // switch(expr) {
-        auto out = line();
+        auto out = Line();
         out << "switch(";
         if (!EmitExpression(out, stmt->condition)) {
             return false;
@@ -3973,7 +3973,7 @@
         }
     }
 
-    line() << "}";
+    Line() << "}";
 
     return true;
 }
@@ -4225,13 +4225,13 @@
         return true;
     }
 
-    line(b) << "struct " << StructName(str) << " {";
+    Line(b) << "struct " << StructName(str) << " {";
     {
         ScopedIndent si(b);
         for (auto* mem : str->Members()) {
             auto mem_name = mem->Name().Name();
             auto* ty = mem->Type();
-            auto out = line(b);
+            auto out = Line(b);
             std::string pre, post;
 
             auto& attributes = mem->Attributes();
@@ -4286,7 +4286,7 @@
         }
     }
 
-    line(b) << "};";
+    Line(b) << "};";
     return true;
 }
 
@@ -4320,7 +4320,7 @@
     auto* sem = builder_.Sem().Get(var);
     auto* type = sem->Type()->UnwrapRef();
 
-    auto out = line();
+    auto out = Line();
     if (!EmitTypeAndName(out, type, sem->AddressSpace(), sem->Access(), var->name->symbol.Name())) {
         return false;
     }
@@ -4345,7 +4345,7 @@
     auto* sem = builder_.Sem().Get(let);
     auto* type = sem->Type()->UnwrapRef();
 
-    auto out = line();
+    auto out = Line();
     out << "const ";
     if (!EmitTypeAndName(out, type, builtin::AddressSpace::kUndefined, builtin::Access::kUndefined,
                          let->name->symbol.Name())) {
@@ -4373,7 +4373,7 @@
         auto fn_name = UniqueIdentifier(std::string("tint_") + builtin::str(builtin->Type()));
         std::vector<std::string> parameter_names;
         {
-            auto decl = line(&b);
+            auto decl = Line(&b);
             if (!EmitTypeAndName(decl, builtin->ReturnType(), builtin::AddressSpace::kUndefined,
                                  builtin::Access::kUndefined, fn_name)) {
                 return "";
@@ -4405,8 +4405,8 @@
                 return "";
             }
         }
-        line(&b) << "}";
-        line(&b);
+        Line(&b) << "}";
+        Line(&b);
         return fn_name;
     });
 
diff --git a/src/tint/writer/hlsl/generator_impl.h b/src/tint/writer/hlsl/generator_impl.h
index 3028853..1d8b59c 100644
--- a/src/tint/writer/hlsl/generator_impl.h
+++ b/src/tint/writer/hlsl/generator_impl.h
@@ -79,7 +79,7 @@
     /// Constructor
     /// @param program the program to generate
     explicit GeneratorImpl(const Program* program);
-    ~GeneratorImpl();
+    ~GeneratorImpl() override;
 
     /// @returns true on successful generation; false otherwise
     bool Generate();
diff --git a/src/tint/writer/hlsl/generator_impl_assign_test.cc b/src/tint/writer/hlsl/generator_impl_assign_test.cc
index e1d8300..fe156be 100644
--- a/src/tint/writer/hlsl/generator_impl_assign_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_assign_test.cc
@@ -32,7 +32,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate());
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(void fn() {
   int lhs = 0;
   int rhs = 0;
@@ -53,7 +53,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate());
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(void set_float3(inout float3 vec, int idx, float val) {
   vec = (idx.xxx == int3(0, 1, 2)) ? val.xxx : vec;
 }
@@ -79,7 +79,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate());
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(void fn() {
   float3 lhs = float3(0.0f, 0.0f, 0.0f);
   float rhs = 0.0f;
@@ -100,7 +100,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate());
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(void set_float3(inout float3 vec, int idx, float val) {
   vec = (idx.xxx == int3(0, 1, 2)) ? val.xxx : vec;
 }
@@ -126,7 +126,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate());
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(void set_vector_float4x2(inout float4x2 mat, int col, float2 val) {
   switch (col) {
     case 0: mat[0] = val; break;
@@ -157,7 +157,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate());
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(void fn() {
   float4x2 lhs = float4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
   float2 rhs = float2(0.0f, 0.0f);
@@ -178,7 +178,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate());
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(void set_vector_float4x2(inout float4x2 mat, int col, float2 val) {
   switch (col) {
     case 0: mat[0] = val; break;
@@ -212,7 +212,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate());
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(void set_scalar_float4x2(inout float4x2 mat, int col, int row, float val) {
   switch (col) {
     case 0:
@@ -255,7 +255,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate());
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(void fn() {
   float4x2 lhs = float4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
   float rhs = 0.0f;
@@ -279,7 +279,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate());
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(void set_scalar_float4x2(inout float4x2 mat, int col, int row, float val) {
   switch (col) {
     case 0:
diff --git a/src/tint/writer/hlsl/generator_impl_binary_test.cc b/src/tint/writer/hlsl/generator_impl_binary_test.cc
index 5269dca..a96d4d2 100644
--- a/src/tint/writer/hlsl/generator_impl_binary_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_binary_test.cc
@@ -410,7 +410,7 @@
     utils::StringStream out;
     ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "(tint_tmp)");
-    EXPECT_EQ(gen.result(), R"(bool tint_tmp = a;
+    EXPECT_EQ(gen.Result(), R"(bool tint_tmp = a;
 if (tint_tmp) {
   tint_tmp = b;
 }
@@ -435,7 +435,7 @@
     utils::StringStream out;
     ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "(tint_tmp)");
-    EXPECT_EQ(gen.result(), R"(bool tint_tmp_1 = a;
+    EXPECT_EQ(gen.Result(), R"(bool tint_tmp_1 = a;
 if (tint_tmp_1) {
   tint_tmp_1 = b;
 }
@@ -462,7 +462,7 @@
     utils::StringStream out;
     ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "(tint_tmp)");
-    EXPECT_EQ(gen.result(), R"(bool tint_tmp = a;
+    EXPECT_EQ(gen.Result(), R"(bool tint_tmp = a;
 if (!tint_tmp) {
   tint_tmp = b;
 }
@@ -492,7 +492,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.EmitStatement(expr)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(bool tint_tmp = a;
+    EXPECT_EQ(gen.Result(), R"(bool tint_tmp = a;
 if (tint_tmp) {
   tint_tmp = b;
 }
@@ -528,7 +528,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.EmitStatement(expr)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(bool tint_tmp_1 = a;
+    EXPECT_EQ(gen.Result(), R"(bool tint_tmp_1 = a;
 if (tint_tmp_1) {
   tint_tmp_1 = b;
 }
@@ -559,7 +559,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.EmitStatement(expr)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(bool tint_tmp_1 = b;
+    EXPECT_EQ(gen.Result(), R"(bool tint_tmp_1 = b;
 if (!tint_tmp_1) {
   tint_tmp_1 = c;
 }
@@ -591,7 +591,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.EmitStatement(decl)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(bool tint_tmp_1 = b;
+    EXPECT_EQ(gen.Result(), R"(bool tint_tmp_1 = b;
 if (tint_tmp_1) {
   tint_tmp_1 = c;
 }
@@ -633,7 +633,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.EmitStatement(expr)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(bool tint_tmp = a;
+    EXPECT_EQ(gen.Result(), R"(bool tint_tmp = a;
 if (tint_tmp) {
   tint_tmp = b;
 }
diff --git a/src/tint/writer/hlsl/generator_impl_block_test.cc b/src/tint/writer/hlsl/generator_impl_block_test.cc
index 0ac0e77..ab01bef 100644
--- a/src/tint/writer/hlsl/generator_impl_block_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_block_test.cc
@@ -25,10 +25,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(b)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     return;
   }
 )");
diff --git a/src/tint/writer/hlsl/generator_impl_break_test.cc b/src/tint/writer/hlsl/generator_impl_break_test.cc
index cad81b4..9cd6254 100644
--- a/src/tint/writer/hlsl/generator_impl_break_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_break_test.cc
@@ -25,10 +25,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(b)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "  break;\n");
+    EXPECT_EQ(gen.Result(), "  break;\n");
 }
 
 }  // namespace
diff --git a/src/tint/writer/hlsl/generator_impl_builtin_test.cc b/src/tint/writer/hlsl/generator_impl_builtin_test.cc
index 16dfcea..1504468 100644
--- a/src/tint/writer/hlsl/generator_impl_builtin_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_builtin_test.cc
@@ -348,7 +348,7 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     utils::StringStream out;
     ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "dot(param1, param2)");
@@ -361,7 +361,7 @@
     WrapInFunction(Decl(Var("r", call)));
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     utils::StringStream out;
     ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "(true ? b : a)");
@@ -374,7 +374,7 @@
     WrapInFunction(Decl(Var("r", call)));
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     utils::StringStream out;
     ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "(bool2(true, false) ? b : a)");
@@ -387,7 +387,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct modf_result_f32 {
+    EXPECT_EQ(gen.Result(), R"(struct modf_result_f32 {
   float fract;
   float whole;
 };
@@ -415,7 +415,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct modf_result_f16 {
+    EXPECT_EQ(gen.Result(), R"(struct modf_result_f16 {
   float16_t fract;
   float16_t whole;
 };
@@ -441,7 +441,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct modf_result_vec3_f32 {
+    EXPECT_EQ(gen.Result(), R"(struct modf_result_vec3_f32 {
   float3 fract;
   float3 whole;
 };
@@ -469,7 +469,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct modf_result_vec3_f16 {
+    EXPECT_EQ(gen.Result(), R"(struct modf_result_vec3_f16 {
   vector<float16_t, 3> fract;
   vector<float16_t, 3> whole;
 };
@@ -494,7 +494,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct modf_result_f32 {
+    EXPECT_EQ(gen.Result(), R"(struct modf_result_f32 {
   float fract;
   float whole;
 };
@@ -514,7 +514,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct modf_result_f16 {
+    EXPECT_EQ(gen.Result(), R"(struct modf_result_f16 {
   float16_t fract;
   float16_t whole;
 };
@@ -532,7 +532,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct modf_result_vec3_f32 {
+    EXPECT_EQ(gen.Result(), R"(struct modf_result_vec3_f32 {
   float3 fract;
   float3 whole;
 };
@@ -552,7 +552,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct modf_result_vec3_f16 {
+    EXPECT_EQ(gen.Result(), R"(struct modf_result_vec3_f16 {
   vector<float16_t, 3> fract;
   vector<float16_t, 3> whole;
 };
@@ -576,7 +576,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct modf_result_vec3_f32 {
+    EXPECT_EQ(gen.Result(), R"(struct modf_result_vec3_f32 {
   float3 fract;
   float3 whole;
 };
@@ -597,7 +597,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct frexp_result_f32 {
+    EXPECT_EQ(gen.Result(), R"(struct frexp_result_f32 {
   float fract;
   int exp;
 };
@@ -626,7 +626,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct frexp_result_f16 {
+    EXPECT_EQ(gen.Result(), R"(struct frexp_result_f16 {
   float16_t fract;
   int exp;
 };
@@ -653,7 +653,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct frexp_result_vec3_f32 {
+    EXPECT_EQ(gen.Result(), R"(struct frexp_result_vec3_f32 {
   float3 fract;
   int3 exp;
 };
@@ -682,7 +682,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct frexp_result_vec3_f16 {
+    EXPECT_EQ(gen.Result(), R"(struct frexp_result_vec3_f16 {
   vector<float16_t, 3> fract;
   int3 exp;
 };
@@ -708,7 +708,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct frexp_result_f32 {
+    EXPECT_EQ(gen.Result(), R"(struct frexp_result_f32 {
   float fract;
   int exp;
 };
@@ -728,7 +728,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct frexp_result_f16 {
+    EXPECT_EQ(gen.Result(), R"(struct frexp_result_f16 {
   float16_t fract;
   int exp;
 };
@@ -746,7 +746,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct frexp_result_vec3_f32 {
+    EXPECT_EQ(gen.Result(), R"(struct frexp_result_vec3_f32 {
   float3 fract;
   int3 exp;
 };
@@ -766,7 +766,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct frexp_result_vec3_f16 {
+    EXPECT_EQ(gen.Result(), R"(struct frexp_result_vec3_f16 {
   vector<float16_t, 3> fract;
   int3 exp;
 };
@@ -790,7 +790,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct frexp_result_vec3_f32 {
+    EXPECT_EQ(gen.Result(), R"(struct frexp_result_vec3_f32 {
   float3 fract;
   int3 exp;
 };
@@ -812,7 +812,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(float tint_degrees(float param_0) {
+    EXPECT_EQ(gen.Result(), R"(float tint_degrees(float param_0) {
   return param_0 * 57.29577951308232286465;
 }
 
@@ -833,7 +833,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(float3 tint_degrees(float3 param_0) {
+    EXPECT_EQ(gen.Result(), R"(float3 tint_degrees(float3 param_0) {
   return param_0 * 57.29577951308232286465;
 }
 
@@ -856,7 +856,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(float16_t tint_degrees(float16_t param_0) {
+    EXPECT_EQ(gen.Result(), R"(float16_t tint_degrees(float16_t param_0) {
   return param_0 * 57.29577951308232286465;
 }
 
@@ -879,7 +879,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(vector<float16_t, 3> tint_degrees(vector<float16_t, 3> param_0) {
+    EXPECT_EQ(gen.Result(), R"(vector<float16_t, 3> tint_degrees(vector<float16_t, 3> param_0) {
   return param_0 * 57.29577951308232286465;
 }
 
@@ -900,7 +900,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(float tint_radians(float param_0) {
+    EXPECT_EQ(gen.Result(), R"(float tint_radians(float param_0) {
   return param_0 * 0.01745329251994329547;
 }
 
@@ -921,7 +921,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(float3 tint_radians(float3 param_0) {
+    EXPECT_EQ(gen.Result(), R"(float3 tint_radians(float3 param_0) {
   return param_0 * 0.01745329251994329547;
 }
 
@@ -944,7 +944,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(float16_t tint_radians(float16_t param_0) {
+    EXPECT_EQ(gen.Result(), R"(float16_t tint_radians(float16_t param_0) {
   return param_0 * 0.01745329251994329547;
 }
 
@@ -967,7 +967,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(vector<float16_t, 3> tint_radians(vector<float16_t, 3> param_0) {
+    EXPECT_EQ(gen.Result(), R"(vector<float16_t, 3> tint_radians(vector<float16_t, 3> param_0) {
   return param_0 * 0.01745329251994329547;
 }
 
@@ -988,7 +988,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"([numthreads(1, 1, 1)]
+    EXPECT_EQ(gen.Result(), R"([numthreads(1, 1, 1)]
 void test_function() {
   int val = 0;
   const int tint_symbol = int(sign(val));
@@ -1005,7 +1005,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"([numthreads(1, 1, 1)]
+    EXPECT_EQ(gen.Result(), R"([numthreads(1, 1, 1)]
 void test_function() {
   int3 val = int3(0, 0, 0);
   const int3 tint_symbol = int3(sign(val));
@@ -1022,7 +1022,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"([numthreads(1, 1, 1)]
+    EXPECT_EQ(gen.Result(), R"([numthreads(1, 1, 1)]
 void test_function() {
   float val = 0.0f;
   const float tint_symbol = float(sign(val));
@@ -1039,7 +1039,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"([numthreads(1, 1, 1)]
+    EXPECT_EQ(gen.Result(), R"([numthreads(1, 1, 1)]
 void test_function() {
   float3 val = float3(0.0f, 0.0f, 0.0f);
   const float3 tint_symbol = float3(sign(val));
@@ -1058,7 +1058,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"([numthreads(1, 1, 1)]
+    EXPECT_EQ(gen.Result(), R"([numthreads(1, 1, 1)]
 void test_function() {
   float16_t val = float16_t(0.0h);
   const float16_t tint_symbol = float16_t(sign(val));
@@ -1077,7 +1077,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"([numthreads(1, 1, 1)]
+    EXPECT_EQ(gen.Result(), R"([numthreads(1, 1, 1)]
 void test_function() {
   vector<float16_t, 3> val = vector<float16_t, 3>(float16_t(0.0h), float16_t(0.0h), float16_t(0.0h));
   const vector<float16_t, 3> tint_symbol = vector<float16_t, 3>(sign(val));
@@ -1094,7 +1094,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(float tint_trunc(float param_0) {
+    EXPECT_EQ(gen.Result(), R"(float tint_trunc(float param_0) {
   return param_0 < 0 ? ceil(param_0) : floor(param_0);
 }
 
@@ -1115,7 +1115,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(float3 tint_trunc(float3 param_0) {
+    EXPECT_EQ(gen.Result(), R"(float3 tint_trunc(float3 param_0) {
   return param_0 < 0 ? ceil(param_0) : floor(param_0);
 }
 
@@ -1138,7 +1138,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(float16_t tint_trunc(float16_t param_0) {
+    EXPECT_EQ(gen.Result(), R"(float16_t tint_trunc(float16_t param_0) {
   return param_0 < 0 ? ceil(param_0) : floor(param_0);
 }
 
@@ -1161,7 +1161,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(vector<float16_t, 3> tint_trunc(vector<float16_t, 3> param_0) {
+    EXPECT_EQ(gen.Result(), R"(vector<float16_t, 3> tint_trunc(vector<float16_t, 3> param_0) {
   return param_0 < 0 ? ceil(param_0) : floor(param_0);
 }
 
@@ -1181,7 +1181,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(uint tint_pack4x8snorm(float4 param_0) {
+    EXPECT_EQ(gen.Result(), R"(uint tint_pack4x8snorm(float4 param_0) {
   int4 i = int4(round(clamp(param_0, -1.0, 1.0) * 127.0)) & 0xff;
   return asuint(i.x | i.y << 8 | i.z << 16 | i.w << 24);
 }
@@ -1203,7 +1203,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(uint tint_pack4x8unorm(float4 param_0) {
+    EXPECT_EQ(gen.Result(), R"(uint tint_pack4x8unorm(float4 param_0) {
   uint4 i = uint4(round(clamp(param_0, 0.0, 1.0) * 255.0));
   return (i.x | i.y << 8 | i.z << 16 | i.w << 24);
 }
@@ -1225,7 +1225,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(uint tint_pack2x16snorm(float2 param_0) {
+    EXPECT_EQ(gen.Result(), R"(uint tint_pack2x16snorm(float2 param_0) {
   int2 i = int2(round(clamp(param_0, -1.0, 1.0) * 32767.0)) & 0xffff;
   return asuint(i.x | i.y << 16);
 }
@@ -1247,7 +1247,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(uint tint_pack2x16unorm(float2 param_0) {
+    EXPECT_EQ(gen.Result(), R"(uint tint_pack2x16unorm(float2 param_0) {
   uint2 i = uint2(round(clamp(param_0, 0.0, 1.0) * 65535.0));
   return (i.x | i.y << 16);
 }
@@ -1269,7 +1269,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(uint tint_pack2x16float(float2 param_0) {
+    EXPECT_EQ(gen.Result(), R"(uint tint_pack2x16float(float2 param_0) {
   uint2 i = f32tof16(param_0);
   return i.x | (i.y << 16);
 }
@@ -1291,7 +1291,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(float4 tint_unpack4x8snorm(uint param_0) {
+    EXPECT_EQ(gen.Result(), R"(float4 tint_unpack4x8snorm(uint param_0) {
   int j = int(param_0);
   int4 i = int4(j << 24, j << 16, j << 8, j) >> 24;
   return clamp(float4(i) / 127.0, -1.0, 1.0);
@@ -1314,7 +1314,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(float4 tint_unpack4x8unorm(uint param_0) {
+    EXPECT_EQ(gen.Result(), R"(float4 tint_unpack4x8unorm(uint param_0) {
   uint j = param_0;
   uint4 i = uint4(j & 0xff, (j >> 8) & 0xff, (j >> 16) & 0xff, j >> 24);
   return float4(i) / 255.0;
@@ -1337,7 +1337,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(float2 tint_unpack2x16snorm(uint param_0) {
+    EXPECT_EQ(gen.Result(), R"(float2 tint_unpack2x16snorm(uint param_0) {
   int j = int(param_0);
   int2 i = int2(j << 16, j) >> 16;
   return clamp(float2(i) / 32767.0, -1.0, 1.0);
@@ -1360,7 +1360,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(float2 tint_unpack2x16unorm(uint param_0) {
+    EXPECT_EQ(gen.Result(), R"(float2 tint_unpack2x16unorm(uint param_0) {
   uint j = param_0;
   uint2 i = uint2(j & 0xffff, j >> 16);
   return float2(i) / 65535.0;
@@ -1383,7 +1383,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(float2 tint_unpack2x16float(uint param_0) {
+    EXPECT_EQ(gen.Result(), R"(float2 tint_unpack2x16float(uint param_0) {
   uint i = param_0;
   return f16tof32(uint2(i & 0xffff, i >> 16));
 }
@@ -1411,7 +1411,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"([numthreads(1, 1, 1)]
+    EXPECT_EQ(gen.Result(), R"([numthreads(1, 1, 1)]
 void main() {
   DeviceMemoryBarrierWithGroupSync();
   return;
@@ -1432,7 +1432,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"([numthreads(1, 1, 1)]
+    EXPECT_EQ(gen.Result(), R"([numthreads(1, 1, 1)]
 void main() {
   GroupMemoryBarrierWithGroupSync();
   return;
@@ -1451,7 +1451,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(int tint_dot4I8Packed(uint param_0, uint param_1) {
+    EXPECT_EQ(gen.Result(), R"(int tint_dot4I8Packed(uint param_0, uint param_1) {
   int accumulator = 0;
   return dot4add_i8packed(param_0, param_1, accumulator);
 }
@@ -1477,7 +1477,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(uint tint_dot4U8Packed(uint param_0, uint param_1) {
+    EXPECT_EQ(gen.Result(), R"(uint tint_dot4U8Packed(uint param_0, uint param_1) {
   uint accumulator = 0u;
   return dot4add_u8packed(param_0, param_1, accumulator);
 }
@@ -1500,7 +1500,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"([numthreads(1, 1, 1)]
+    EXPECT_EQ(gen.Result(), R"([numthreads(1, 1, 1)]
 void test_function() {
   int val1 = 0;
   const int tint_symbol = asint(countbits(asuint(val1)));
@@ -1517,7 +1517,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"([numthreads(1, 1, 1)]
+    EXPECT_EQ(gen.Result(), R"([numthreads(1, 1, 1)]
 void test_function() {
   int val1 = 0;
   const int tint_symbol = asint(reversebits(asuint(val1)));
diff --git a/src/tint/writer/hlsl/generator_impl_builtin_texture_test.cc b/src/tint/writer/hlsl/generator_impl_builtin_texture_test.cc
index 8ddcc1c..12bd221 100644
--- a/src/tint/writer/hlsl/generator_impl_builtin_texture_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_builtin_texture_test.cc
@@ -384,8 +384,8 @@
 
     auto expected = expected_texture_overload(param.overload);
 
-    EXPECT_THAT(gen.result(), HasSubstr(expected.pre));
-    EXPECT_THAT(gen.result(), HasSubstr(expected.out));
+    EXPECT_THAT(gen.Result(), HasSubstr(expected.pre));
+    EXPECT_THAT(gen.Result(), HasSubstr(expected.out));
 }
 
 INSTANTIATE_TEST_SUITE_P(HlslGeneratorBuiltinTextureTest,
diff --git a/src/tint/writer/hlsl/generator_impl_call_test.cc b/src/tint/writer/hlsl/generator_impl_call_test.cc
index 80bacb6..21a6373 100644
--- a/src/tint/writer/hlsl/generator_impl_call_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_call_test.cc
@@ -71,9 +71,9 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     ASSERT_TRUE(gen.EmitStatement(call)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "  my_func(param1, param2);\n");
+    EXPECT_EQ(gen.Result(), "  my_func(param1, param2);\n");
 }
 
 }  // namespace
diff --git a/src/tint/writer/hlsl/generator_impl_case_test.cc b/src/tint/writer/hlsl/generator_impl_case_test.cc
index 523de31..1956485 100644
--- a/src/tint/writer/hlsl/generator_impl_case_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_case_test.cc
@@ -28,10 +28,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitCase(s, 0)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  case 5: {
+    EXPECT_EQ(gen.Result(), R"(  case 5: {
     break;
   }
 )");
@@ -43,10 +43,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitCase(s, 0)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  case 5: {
+    EXPECT_EQ(gen.Result(), R"(  case 5: {
     break;
   }
 )");
@@ -61,10 +61,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitCase(s, 0)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  case 5:
+    EXPECT_EQ(gen.Result(), R"(  case 5:
   case 6: {
     break;
   }
@@ -77,10 +77,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitCase(s, 0u)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  default: {
+    EXPECT_EQ(gen.Result(), R"(  default: {
     break;
   }
 )");
diff --git a/src/tint/writer/hlsl/generator_impl_const_assert_test.cc b/src/tint/writer/hlsl/generator_impl_const_assert_test.cc
index 52548db..2791568 100644
--- a/src/tint/writer/hlsl/generator_impl_const_assert_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_const_assert_test.cc
@@ -28,7 +28,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
     // const asserts are not emitted
-    EXPECT_EQ(gen.result(), "");
+    EXPECT_EQ(gen.Result(), "");
 }
 
 TEST_F(HlslGeneratorImplTest, Emit_FunctionConstAssert) {
@@ -38,7 +38,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
     // const asserts are not emitted
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
 }
 )");
 }
diff --git a/src/tint/writer/hlsl/generator_impl_constructor_test.cc b/src/tint/writer/hlsl/generator_impl_constructor_test.cc
index bdb05ba..42a00ae 100644
--- a/src/tint/writer/hlsl/generator_impl_constructor_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_constructor_test.cc
@@ -30,7 +30,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("false"));
+    EXPECT_THAT(gen.Result(), HasSubstr("false"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, Int) {
@@ -39,7 +39,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("-12345"));
+    EXPECT_THAT(gen.Result(), HasSubstr("-12345"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, UInt) {
@@ -48,7 +48,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("56779u"));
+    EXPECT_THAT(gen.Result(), HasSubstr("56779u"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, Float) {
@@ -58,7 +58,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("1073741824.0f"));
+    EXPECT_THAT(gen.Result(), HasSubstr("1073741824.0f"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, F16) {
@@ -70,7 +70,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("float16_t(32752.0h)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("float16_t(32752.0h)"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, Type_Float) {
@@ -79,7 +79,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("-0.00001200000042445026f"));
+    EXPECT_THAT(gen.Result(), HasSubstr("-0.00001200000042445026f"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, Type_F16) {
@@ -90,7 +90,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("float16_t(-0.0011997222900390625h)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("float16_t(-0.0011997222900390625h)"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, Type_Bool) {
@@ -99,7 +99,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("true"));
+    EXPECT_THAT(gen.Result(), HasSubstr("true"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, Type_Int) {
@@ -108,7 +108,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("-12345"));
+    EXPECT_THAT(gen.Result(), HasSubstr("-12345"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, Type_Uint) {
@@ -117,7 +117,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("12345u"));
+    EXPECT_THAT(gen.Result(), HasSubstr("12345u"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, Type_Vec_F32) {
@@ -126,7 +126,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("float3(1.0f, 2.0f, 3.0f)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("float3(1.0f, 2.0f, 3.0f)"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, Type_Vec_F16) {
@@ -138,7 +138,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
     EXPECT_THAT(
-        gen.result(),
+        gen.Result(),
         HasSubstr("vector<float16_t, 3>(float16_t(1.0h), float16_t(2.0h), float16_t(3.0h))"));
 }
 
@@ -148,7 +148,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("0.0f).xxx"));
+    EXPECT_THAT(gen.Result(), HasSubstr("0.0f).xxx"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, Type_Vec_Empty_F16) {
@@ -159,7 +159,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("(float16_t(0.0h)).xxx"));
+    EXPECT_THAT(gen.Result(), HasSubstr("(float16_t(0.0h)).xxx"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_F32_Literal) {
@@ -168,7 +168,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("2.0f).xxx"));
+    EXPECT_THAT(gen.Result(), HasSubstr("2.0f).xxx"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_F16_Literal) {
@@ -179,7 +179,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("(float16_t(2.0h)).xxx"));
+    EXPECT_THAT(gen.Result(), HasSubstr("(float16_t(2.0h)).xxx"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_F32_Var) {
@@ -190,7 +190,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr(R"(float v = 2.0f;
+    EXPECT_THAT(gen.Result(), HasSubstr(R"(float v = 2.0f;
   const float3 tint_symbol = float3((v).xxx);)"));
 }
 
@@ -204,7 +204,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr(R"(float16_t v = float16_t(2.0h);
+    EXPECT_THAT(gen.Result(), HasSubstr(R"(float16_t v = float16_t(2.0h);
   const vector<float16_t, 3> tint_symbol = vector<float16_t, 3>((v).xxx);)"));
 }
 
@@ -214,7 +214,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("(true).xxx"));
+    EXPECT_THAT(gen.Result(), HasSubstr("(true).xxx"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_Bool_Var) {
@@ -225,7 +225,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr(R"(bool v = true;
+    EXPECT_THAT(gen.Result(), HasSubstr(R"(bool v = true;
   const bool3 tint_symbol = bool3((v).xxx);)"));
 }
 
@@ -235,7 +235,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("2).xxx"));
+    EXPECT_THAT(gen.Result(), HasSubstr("2).xxx"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_UInt) {
@@ -244,7 +244,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("2u).xxx"));
+    EXPECT_THAT(gen.Result(), HasSubstr("2u).xxx"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, Type_Mat_F32) {
@@ -255,7 +255,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_THAT(gen.result(),
+    EXPECT_THAT(gen.Result(),
                 HasSubstr("float2x3(float3(1.0f, 2.0f, 3.0f), float3(3.0f, 4.0f, 5.0f))"));
 }
 
@@ -269,7 +269,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_THAT(gen.result(),
+    EXPECT_THAT(gen.Result(),
                 HasSubstr("matrix<float16_t, 2, 3>(vector<float16_t, 3>(float16_t(1.0h), "
                           "float16_t(2.0h), float16_t(3.0h)), vector<float16_t, "
                           "3>(float16_t(3.0h), float16_t(4.0h), float16_t(5.0h)))"));
@@ -297,7 +297,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_THAT(gen.result(), HasSubstr("float4x4(float4(2.0f, 3.0f, 4.0f, 8.0f), (0.0f).xxxx, "
+    EXPECT_THAT(gen.Result(), HasSubstr("float4x4(float4(2.0f, 3.0f, 4.0f, 8.0f), (0.0f).xxxx, "
                                         "(7.0f).xxxx, float4(42.0f, 21.0f, 6.0f, -5.0f))"));
 }
 
@@ -325,7 +325,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_THAT(gen.result(), HasSubstr("matrix<float16_t, 4, 4>("
+    EXPECT_THAT(gen.Result(), HasSubstr("matrix<float16_t, 4, 4>("
                                         "vector<float16_t, 4>(float16_t(2.0h), float16_t(3.0h), "
                                         "float16_t(4.0h), float16_t(8.0h)), "
                                         "(float16_t(0.0h)).xxxx, (float16_t(7.0h)).xxxx, "
@@ -340,7 +340,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_THAT(gen.result(), HasSubstr("float2x3 tint_symbol = float2x3((0.0f).xxx, (0.0f).xxx)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("float2x3 tint_symbol = float2x3((0.0f).xxx, (0.0f).xxx)"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, Type_Mat_Empty_F16) {
@@ -352,7 +352,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_THAT(gen.result(),
+    EXPECT_THAT(gen.Result(),
                 HasSubstr("matrix<float16_t, 2, 3>((float16_t(0.0h)).xxx, (float16_t(0.0h)).xxx)"));
 }
 
@@ -371,7 +371,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_THAT(gen.result(), HasSubstr("float4x4 m_2 = float4x4(m_1);"));
+    EXPECT_THAT(gen.Result(), HasSubstr("float4x4 m_2 = float4x4(m_1);"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, Type_Mat_Identity_F16) {
@@ -391,7 +391,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_THAT(gen.result(),
+    EXPECT_THAT(gen.Result(),
                 HasSubstr("matrix<float16_t, 4, 4> m_2 = matrix<float16_t, 4, 4>(m_1);"));
 }
 
@@ -404,7 +404,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
     EXPECT_THAT(
-        gen.result(),
+        gen.Result(),
         HasSubstr(
             "{float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f), float3(7.0f, 8.0f, 9.0f)}"));
 }
@@ -415,7 +415,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("(float3[3])0"));
+    EXPECT_THAT(gen.Result(), HasSubstr("(float3[3])0"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, Type_Struct) {
@@ -430,7 +430,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("{1, 2.0f, int3(3, 4, 5)}"));
+    EXPECT_THAT(gen.Result(), HasSubstr("{1, 2.0f, int3(3, 4, 5)}"));
 }
 
 TEST_F(HlslGeneratorImplTest_Constructor, Type_Struct_Empty) {
@@ -445,7 +445,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("(S)0"));
+    EXPECT_THAT(gen.Result(), HasSubstr("(S)0"));
 }
 
 }  // namespace
diff --git a/src/tint/writer/hlsl/generator_impl_continue_test.cc b/src/tint/writer/hlsl/generator_impl_continue_test.cc
index 936d515..8a7d5ce 100644
--- a/src/tint/writer/hlsl/generator_impl_continue_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_continue_test.cc
@@ -26,10 +26,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(loop)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  while (true) {
+    EXPECT_EQ(gen.Result(), R"(  while (true) {
     if (false) {
       break;
     }
diff --git a/src/tint/writer/hlsl/generator_impl_discard_test.cc b/src/tint/writer/hlsl/generator_impl_discard_test.cc
index 9a7d1a5..b34561a 100644
--- a/src/tint/writer/hlsl/generator_impl_discard_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_discard_test.cc
@@ -27,10 +27,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "  discard;\n");
+    EXPECT_EQ(gen.Result(), "  discard;\n");
 }
 
 }  // namespace
diff --git a/src/tint/writer/hlsl/generator_impl_function_test.cc b/src/tint/writer/hlsl/generator_impl_function_test.cc
index a374924..3a69948 100644
--- a/src/tint/writer/hlsl/generator_impl_function_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_function_test.cc
@@ -36,10 +36,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  void my_func() {
+    EXPECT_EQ(gen.Result(), R"(  void my_func() {
     return;
   }
 )");
@@ -53,10 +53,10 @@
 
     GeneratorImpl& gen = SanitizeAndBuild();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr(R"(  void tint_symbol() {
+    EXPECT_THAT(gen.Result(), HasSubstr(R"(  void tint_symbol() {
     return;
   })"));
 }
@@ -74,10 +74,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  void my_func(float a, int b) {
+    EXPECT_EQ(gen.Result(), R"(  void my_func(float a, int b) {
     return;
   }
 )");
@@ -92,7 +92,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(void main() {
+    EXPECT_EQ(gen.Result(), R"(void main() {
   return;
 }
 )");
@@ -108,7 +108,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr(R"(float f(inout float foo) {
+    EXPECT_THAT(gen.Result(), HasSubstr(R"(float f(inout float foo) {
   return foo;
 }
 )"));
@@ -133,7 +133,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct tint_symbol_1 {
+    EXPECT_EQ(gen.Result(), R"(struct tint_symbol_1 {
   float foo : TEXCOORD0;
 };
 struct tint_symbol_2 {
@@ -173,7 +173,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct tint_symbol_1 {
+    EXPECT_EQ(gen.Result(), R"(struct tint_symbol_1 {
   float4 coord : SV_Position;
 };
 struct tint_symbol_2 {
@@ -232,7 +232,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct Interface {
+    EXPECT_EQ(gen.Result(), R"(struct Interface {
   float4 pos;
   float col1;
   float col2;
@@ -316,7 +316,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct VertexOutput {
+    EXPECT_EQ(gen.Result(), R"(struct VertexOutput {
   float4 pos;
 };
 
@@ -385,7 +385,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(cbuffer cbuffer_ubo : register(b0, space1) {
+    EXPECT_EQ(gen.Result(), R"(cbuffer cbuffer_ubo : register(b0, space1) {
   uint4 ubo[1];
 };
 
@@ -419,7 +419,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(cbuffer cbuffer_uniforms : register(b0, space1) {
+    EXPECT_EQ(gen.Result(), R"(cbuffer cbuffer_uniforms : register(b0, space1) {
   uint4 uniforms[1];
 };
 
@@ -453,7 +453,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(RWByteAddressBuffer coord : register(u0, space1);
 
 void frag_main() {
@@ -486,7 +486,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(ByteAddressBuffer coord : register(t0, space1);
 
 void frag_main() {
@@ -517,7 +517,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(RWByteAddressBuffer coord : register(u0, space1);
 
 void frag_main() {
@@ -548,7 +548,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(RWByteAddressBuffer coord : register(u0, space1);
 
 void frag_main() {
@@ -585,7 +585,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(cbuffer cbuffer_coord : register(b0, space1) {
+    EXPECT_EQ(gen.Result(), R"(cbuffer cbuffer_coord : register(b0, space1) {
   uint4 coord[1];
 };
 
@@ -628,7 +628,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(RWByteAddressBuffer coord : register(u0, space1);
 
 float sub_func(float param) {
@@ -651,7 +651,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(void tint_symbol() {
+    EXPECT_EQ(gen.Result(), R"(void tint_symbol() {
   return;
 }
 )");
@@ -667,7 +667,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"([numthreads(1, 1, 1)]
+    EXPECT_EQ(gen.Result(), R"([numthreads(1, 1, 1)]
 void main() {
   return;
 }
@@ -684,7 +684,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"([numthreads(2, 4, 6)]
+    EXPECT_EQ(gen.Result(), R"([numthreads(2, 4, 6)]
 void main() {
   return;
 }
@@ -704,7 +704,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"([numthreads(2, 3, 4)]
+    EXPECT_EQ(gen.Result(), R"([numthreads(2, 3, 4)]
 void main() {
   return;
 }
@@ -743,7 +743,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(void my_func(float a[5]) {
+    EXPECT_EQ(gen.Result(), R"(void my_func(float a[5]) {
   return;
 }
 )");
@@ -758,7 +758,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(typedef float my_func_ret[5];
+    EXPECT_EQ(gen.Result(), R"(typedef float my_func_ret[5];
 my_func_ret my_func() {
   return (float[5])0;
 }
@@ -776,7 +776,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(void my_func(int a) {
+    EXPECT_EQ(gen.Result(), R"(void my_func(int a) {
   if ((a == 0)) {
     discard;
   }
@@ -796,7 +796,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(int my_func(int a) {
+    EXPECT_EQ(gen.Result(), R"(int my_func(int a) {
   if (true) {
     if ((a == 0)) {
       discard;
@@ -864,7 +864,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(RWByteAddressBuffer data : register(u0);
+    EXPECT_EQ(gen.Result(), R"(RWByteAddressBuffer data : register(u0);
 
 [numthreads(1, 1, 1)]
 void a() {
diff --git a/src/tint/writer/hlsl/generator_impl_if_test.cc b/src/tint/writer/hlsl/generator_impl_if_test.cc
index 764c40e..867e12e 100644
--- a/src/tint/writer/hlsl/generator_impl_if_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_if_test.cc
@@ -29,9 +29,9 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     ASSERT_TRUE(gen.EmitStatement(i)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  if (cond) {
+    EXPECT_EQ(gen.Result(), R"(  if (cond) {
     return;
   }
 )");
@@ -51,10 +51,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(i)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  if (cond) {
+    EXPECT_EQ(gen.Result(), R"(  if (cond) {
     return;
   } else {
     if (else_cond) {
@@ -76,10 +76,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(i)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  if (cond) {
+    EXPECT_EQ(gen.Result(), R"(  if (cond) {
     return;
   } else {
     return;
@@ -104,10 +104,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(i)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  if (cond) {
+    EXPECT_EQ(gen.Result(), R"(  if (cond) {
     return;
   } else {
     if (else_cond) {
diff --git a/src/tint/writer/hlsl/generator_impl_loop_test.cc b/src/tint/writer/hlsl/generator_impl_loop_test.cc
index d8ec84b..bbaf410 100644
--- a/src/tint/writer/hlsl/generator_impl_loop_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_loop_test.cc
@@ -32,10 +32,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(l)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  while (true) {
+    EXPECT_EQ(gen.Result(), R"(  while (true) {
     break;
   }
 )");
@@ -53,10 +53,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(l)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  while (true) {
+    EXPECT_EQ(gen.Result(), R"(  while (true) {
     break;
     {
       a_statement();
@@ -77,10 +77,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(l)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  while (true) {
+    EXPECT_EQ(gen.Result(), R"(  while (true) {
     break;
     {
       a_statement();
@@ -114,10 +114,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(outer)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  while (true) {
+    EXPECT_EQ(gen.Result(), R"(  while (true) {
     while (true) {
       break;
       {
@@ -154,10 +154,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(outer)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  while (true) {
+    EXPECT_EQ(gen.Result(), R"(  while (true) {
     float lhs = 2.5f;
     float other = 0.0f;
     break;
@@ -178,10 +178,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     for(; ; ) {
       return;
     }
@@ -199,10 +199,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     for(int i = 0; ; ) {
       return;
     }
@@ -223,10 +223,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     bool tint_tmp = t;
     if (tint_tmp) {
       tint_tmp = false;
@@ -249,10 +249,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     for(; true; ) {
       return;
     }
@@ -274,10 +274,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     while (true) {
       bool tint_tmp = t;
       if (tint_tmp) {
@@ -301,10 +301,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     for(; ; i = (i + 1)) {
       return;
     }
@@ -327,10 +327,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     while (true) {
       return;
       bool tint_tmp = t;
@@ -353,10 +353,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     for(int i = 0; true; i = (i + 1)) {
       return;
     }
@@ -381,10 +381,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     bool tint_tmp = t;
     if (tint_tmp) {
       tint_tmp = false;
@@ -417,10 +417,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  while(true) {
+    EXPECT_EQ(gen.Result(), R"(  while(true) {
     return;
   }
 )");
@@ -436,10 +436,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  while(true) {
+    EXPECT_EQ(gen.Result(), R"(  while(true) {
     continue;
   }
 )");
@@ -460,10 +460,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  while (true) {
+    EXPECT_EQ(gen.Result(), R"(  while (true) {
     bool tint_tmp = t;
     if (tint_tmp) {
       tint_tmp = false;
diff --git a/src/tint/writer/hlsl/generator_impl_member_accessor_test.cc b/src/tint/writer/hlsl/generator_impl_member_accessor_test.cc
index 6232315..ad82452 100644
--- a/src/tint/writer/hlsl/generator_impl_member_accessor_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_member_accessor_test.cc
@@ -131,7 +131,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(struct Data {
+    EXPECT_EQ(gen.Result(), R"(struct Data {
   float mem;
 };
 
@@ -180,7 +180,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr(p.expected));
+    EXPECT_THAT(gen.Result(), HasSubstr(p.expected));
 }
 
 INSTANTIATE_TEST_SUITE_P(
@@ -323,7 +323,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr(p.expected));
+    EXPECT_THAT(gen.Result(), HasSubstr(p.expected));
 }
 
 INSTANTIATE_TEST_SUITE_P(
@@ -454,7 +454,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr(p.expected));
+    EXPECT_THAT(gen.Result(), HasSubstr(p.expected));
 }
 
 INSTANTIATE_TEST_SUITE_P(
@@ -730,7 +730,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr(p.expected));
+    EXPECT_THAT(gen.Result(), HasSubstr(p.expected));
 }
 
 INSTANTIATE_TEST_SUITE_P(
@@ -1005,7 +1005,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr(p.expected));
+    EXPECT_THAT(gen.Result(), HasSubstr(p.expected));
 }
 
 INSTANTIATE_TEST_SUITE_P(
@@ -1153,7 +1153,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Load_Matrix_F32_Single_Element) {
@@ -1184,7 +1184,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Load_Matrix_F16_Single_Element) {
@@ -1217,7 +1217,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor, UniformBuffer_Load_Matrix_F32_Single_Element) {
@@ -1250,7 +1250,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor, UniformBuffer_Load_Matrix_F16_Single_Element) {
@@ -1285,7 +1285,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor,
@@ -1317,7 +1317,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor,
@@ -1351,7 +1351,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor,
@@ -1401,7 +1401,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor,
@@ -1454,7 +1454,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor,
@@ -1492,7 +1492,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor,
@@ -1533,7 +1533,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Store_ToArray) {
@@ -1563,7 +1563,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Load_MultiLevel) {
@@ -1602,7 +1602,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor, UniformBuffer_Load_MultiLevel) {
@@ -1643,7 +1643,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Load_MultiLevel_Swizzle) {
@@ -1684,7 +1684,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor, UniformBuffer_Load_MultiLevel_Swizzle) {
@@ -1727,7 +1727,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor,
@@ -1769,7 +1769,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor,
@@ -1813,7 +1813,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Load_MultiLevel_Index) {
@@ -1854,7 +1854,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor, UniformBuffer_Load_MultiLevel_Index) {
@@ -1897,7 +1897,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Store_MultiLevel) {
@@ -1937,7 +1937,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor, StorageBuffer_Store_Swizzle_SingleLetter) {
@@ -1978,7 +1978,7 @@
   return;
 }
 )";
-    EXPECT_EQ(gen.result(), expected);
+    EXPECT_EQ(gen.Result(), expected);
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor, Swizzle_xyz) {
@@ -1988,7 +1988,7 @@
 
     GeneratorImpl& gen = SanitizeAndBuild();
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("my_vec.xyz"));
+    EXPECT_THAT(gen.Result(), HasSubstr("my_vec.xyz"));
 }
 
 TEST_F(HlslGeneratorImplTest_MemberAccessor, Swizzle_gbr) {
@@ -1998,7 +1998,7 @@
 
     GeneratorImpl& gen = SanitizeAndBuild();
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("my_vec.gbr"));
+    EXPECT_THAT(gen.Result(), HasSubstr("my_vec.gbr"));
 }
 
 }  // namespace
diff --git a/src/tint/writer/hlsl/generator_impl_module_constant_test.cc b/src/tint/writer/hlsl/generator_impl_module_constant_test.cc
index c4e4e01..fdc79d3 100644
--- a/src/tint/writer/hlsl/generator_impl_module_constant_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_module_constant_test.cc
@@ -31,7 +31,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const int l = 1;
 }
 )");
@@ -45,7 +45,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const float l = 1.0f;
 }
 )");
@@ -59,7 +59,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const int l = 1;
 }
 )");
@@ -73,7 +73,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const uint l = 1u;
 }
 )");
@@ -87,7 +87,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const float l = 1.0f;
 }
 )");
@@ -103,7 +103,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const float16_t l = float16_t(1.0h);
 }
 )");
@@ -117,7 +117,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const int3 l = int3(1, 2, 3);
 }
 )");
@@ -131,7 +131,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const float3 l = float3(1.0f, 2.0f, 3.0f);
 }
 )");
@@ -145,7 +145,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const float3 l = float3(1.0f, 2.0f, 3.0f);
 }
 )");
@@ -161,7 +161,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const vector<float16_t, 3> l = vector<float16_t, 3>(float16_t(1.0h), float16_t(2.0h), float16_t(3.0h));
 }
 )");
@@ -175,7 +175,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const float2x3 l = float2x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f));
 }
 )");
@@ -189,7 +189,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const float2x3 l = float2x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f));
 }
 )");
@@ -205,7 +205,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const matrix<float16_t, 2, 3> l = matrix<float16_t, 2, 3>(vector<float16_t, 3>(float16_t(1.0h), float16_t(2.0h), float16_t(3.0h)), vector<float16_t, 3>(float16_t(4.0h), float16_t(5.0h), float16_t(6.0h)));
 }
 )");
@@ -219,7 +219,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const float l[3] = {1.0f, 2.0f, 3.0f};
 }
 )");
@@ -236,7 +236,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const bool2 l[3] = {bool2(true, false), bool2(false, true), (true).xx};
 }
 )");
diff --git a/src/tint/writer/hlsl/generator_impl_return_test.cc b/src/tint/writer/hlsl/generator_impl_return_test.cc
index 7ef52c6..4cdf229 100644
--- a/src/tint/writer/hlsl/generator_impl_return_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_return_test.cc
@@ -27,10 +27,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(r)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "  return;\n");
+    EXPECT_EQ(gen.Result(), "  return;\n");
 }
 
 TEST_F(HlslGeneratorImplTest_Return, Emit_ReturnWithValue) {
@@ -39,10 +39,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(r)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "  return 123;\n");
+    EXPECT_EQ(gen.Result(), "  return 123;\n");
 }
 
 }  // namespace
diff --git a/src/tint/writer/hlsl/generator_impl_sanitizer_test.cc b/src/tint/writer/hlsl/generator_impl_sanitizer_test.cc
index 0d5ed73..9537581 100644
--- a/src/tint/writer/hlsl/generator_impl_sanitizer_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_sanitizer_test.cc
@@ -42,7 +42,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    auto got = gen.result();
+    auto got = gen.Result();
     auto* expect = R"(ByteAddressBuffer b : register(t1, space2);
 
 void a_func() {
@@ -76,7 +76,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    auto got = gen.result();
+    auto got = gen.Result();
     auto* expect = R"(ByteAddressBuffer b : register(t1, space2);
 
 void a_func() {
@@ -113,7 +113,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    auto got = gen.result();
+    auto got = gen.Result();
     auto* expect = R"(ByteAddressBuffer b : register(t1, space2);
 
 void a_func() {
@@ -152,7 +152,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    auto got = gen.result();
+    auto got = gen.Result();
     auto* expect = R"(cbuffer cbuffer_tint_symbol_1 : register(b4, space3) {
   uint4 tint_symbol_1[2];
 };
@@ -186,7 +186,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    auto got = gen.result();
+    auto got = gen.Result();
     auto* expect = R"(void main() {
   int idx = 3;
   const int tint_symbol[4] = {1, 2, 3, 4};
@@ -221,7 +221,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    auto got = gen.result();
+    auto got = gen.Result();
     auto* expect = R"(struct S {
   int a;
   float3 b;
@@ -260,7 +260,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    auto got = gen.result();
+    auto got = gen.Result();
     auto* expect = R"(void main() {
   int v = 0;
   int x = v;
@@ -298,7 +298,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    auto got = gen.result();
+    auto got = gen.Result();
     auto* expect = R"(void main() {
   float4x4 a[4] = (float4x4[4])0;
   float4 v = a[3][2];
diff --git a/src/tint/writer/hlsl/generator_impl_switch_test.cc b/src/tint/writer/hlsl/generator_impl_switch_test.cc
index 427835f..bf11021 100644
--- a/src/tint/writer/hlsl/generator_impl_switch_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_switch_test.cc
@@ -31,10 +31,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(s)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  switch(cond) {
+    EXPECT_EQ(gen.Result(), R"(  switch(cond) {
     case 5: {
       break;
     }
@@ -54,10 +54,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(s)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  switch(cond) {
+    EXPECT_EQ(gen.Result(), R"(  switch(cond) {
     case 5:
     default: {
       break;
@@ -85,10 +85,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(s)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  do {
+    EXPECT_EQ(gen.Result(), R"(  do {
     a = 42;
   } while (false);
 )");
@@ -123,10 +123,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(s)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  bar();
+    EXPECT_EQ(gen.Result(), R"(  bar();
   do {
     a = 42;
   } while (false);
diff --git a/src/tint/writer/hlsl/generator_impl_test.cc b/src/tint/writer/hlsl/generator_impl_test.cc
index 572f71a..c7a54df 100644
--- a/src/tint/writer/hlsl/generator_impl_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_test.cc
@@ -44,7 +44,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(void my_func() {
+    EXPECT_EQ(gen.Result(), R"(void my_func() {
 }
 )");
 }
diff --git a/src/tint/writer/hlsl/generator_impl_type_test.cc b/src/tint/writer/hlsl/generator_impl_type_test.cc
index 337b26b..0739c9a 100644
--- a/src/tint/writer/hlsl/generator_impl_type_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_type_test.cc
@@ -191,7 +191,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "RWByteAddressBuffer g : register(u0);\n");
+    EXPECT_EQ(gen.Result(), "RWByteAddressBuffer g : register(u0);\n");
 }
 
 TEST_F(HlslGeneratorImplTest_Type, EmitType_Struct) {
@@ -221,7 +221,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr(R"(struct S {
+    EXPECT_THAT(gen.Result(), HasSubstr(R"(struct S {
   int tint_symbol;
   float tint_symbol_1;
 };
@@ -337,7 +337,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr(params.result));
+    EXPECT_THAT(gen.Result(), HasSubstr(params.result));
 }
 INSTANTIATE_TEST_SUITE_P(
     HlslGeneratorImplTest_Type,
@@ -368,7 +368,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("Texture2DMS<float4> tex : register(t1, space2);"));
+    EXPECT_THAT(gen.Result(), HasSubstr("Texture2DMS<float4> tex : register(t1, space2);"));
 }
 
 enum class TextureDataType { F32, U32, I32 };
@@ -414,7 +414,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr(params.result));
+    EXPECT_THAT(gen.Result(), HasSubstr(params.result));
 }
 INSTANTIATE_TEST_SUITE_P(HlslGeneratorImplTest_Type,
                          HlslSampledTexturesTest,
@@ -557,7 +557,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr(params.result));
+    EXPECT_THAT(gen.Result(), HasSubstr(params.result));
 }
 INSTANTIATE_TEST_SUITE_P(
     HlslGeneratorImplTest_Type,
diff --git a/src/tint/writer/hlsl/generator_impl_variable_decl_statement_test.cc b/src/tint/writer/hlsl/generator_impl_variable_decl_statement_test.cc
index f53eee2..29fd08f 100644
--- a/src/tint/writer/hlsl/generator_impl_variable_decl_statement_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_variable_decl_statement_test.cc
@@ -33,10 +33,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "  float a = 0.0f;\n");
+    EXPECT_EQ(gen.Result(), "  float a = 0.0f;\n");
 }
 
 TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Let) {
@@ -46,10 +46,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "  const float a = 0.0f;\n");
+    EXPECT_EQ(gen.Result(), "  const float a = 0.0f;\n");
 }
 
 TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const) {
@@ -59,10 +59,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "");  // Not a mistake - 'const' is inlined
+    EXPECT_EQ(gen.Result(), "");  // Not a mistake - 'const' is inlined
 }
 
 TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_AInt) {
@@ -77,7 +77,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const int l = 1;
 }
 )");
@@ -95,7 +95,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const float l = 1.0f;
 }
 )");
@@ -113,7 +113,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const int l = 1;
 }
 )");
@@ -131,7 +131,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const uint l = 1u;
 }
 )");
@@ -149,7 +149,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const float l = 1.0f;
 }
 )");
@@ -169,7 +169,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const float16_t l = float16_t(1.0h);
 }
 )");
@@ -187,7 +187,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const int3 l = int3(1, 2, 3);
 }
 )");
@@ -205,7 +205,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const float3 l = float3(1.0f, 2.0f, 3.0f);
 }
 )");
@@ -223,7 +223,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const float3 l = float3(1.0f, 2.0f, 3.0f);
 }
 )");
@@ -243,7 +243,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const vector<float16_t, 3> l = vector<float16_t, 3>(float16_t(1.0h), float16_t(2.0h), float16_t(3.0h));
 }
 )");
@@ -261,7 +261,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const float2x3 l = float2x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f));
 }
 )");
@@ -279,7 +279,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const float2x3 l = float2x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f));
 }
 )");
@@ -299,7 +299,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const matrix<float16_t, 2, 3> l = matrix<float16_t, 2, 3>(vector<float16_t, 3>(float16_t(1.0h), float16_t(2.0h), float16_t(3.0h)), vector<float16_t, 3>(float16_t(4.0h), float16_t(5.0h), float16_t(6.0h)));
 }
 )");
@@ -317,7 +317,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const float l[3] = {1.0f, 2.0f, 3.0f};
 }
 )");
@@ -338,7 +338,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(void f() {
+    EXPECT_EQ(gen.Result(), R"(void f() {
   const bool2 l[3] = {bool2(true, false), bool2(false, true), (true).xx};
 }
 )");
@@ -351,10 +351,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("  float a[5] = (float[5])0;\n"));
+    EXPECT_THAT(gen.Result(), HasSubstr("  float a[5] = (float[5])0;\n"));
 }
 
 TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Private) {
@@ -364,10 +364,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("  static float a = 0.0f;\n"));
+    EXPECT_THAT(gen.Result(), HasSubstr("  static float a = 0.0f;\n"));
 }
 
 TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Initializer_ZeroVec_F32) {
@@ -379,7 +379,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(float3 a = (0.0f).xxx;
+    EXPECT_EQ(gen.Result(), R"(float3 a = (0.0f).xxx;
 )");
 }
 
@@ -394,7 +394,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(vector<float16_t, 3> a = (float16_t(0.0h)).xxx;
+    EXPECT_EQ(gen.Result(), R"(vector<float16_t, 3> a = (float16_t(0.0h)).xxx;
 )");
 }
 
@@ -407,7 +407,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(float2x3 a = float2x3((0.0f).xxx, (0.0f).xxx);
 )");
 }
@@ -424,7 +424,7 @@
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
     EXPECT_EQ(
-        gen.result(),
+        gen.Result(),
         R"(matrix<float16_t, 2, 3> a = matrix<float16_t, 2, 3>((float16_t(0.0h)).xxx, (float16_t(0.0h)).xxx);
 )");
 }
diff --git a/src/tint/writer/hlsl/generator_impl_workgroup_var_test.cc b/src/tint/writer/hlsl/generator_impl_workgroup_var_test.cc
index 910bc9a..e721427 100644
--- a/src/tint/writer/hlsl/generator_impl_workgroup_var_test.cc
+++ b/src/tint/writer/hlsl/generator_impl_workgroup_var_test.cc
@@ -37,7 +37,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("groupshared float wg;\n"));
+    EXPECT_THAT(gen.Result(), HasSubstr("groupshared float wg;\n"));
 }
 
 TEST_F(HlslGeneratorImplTest_WorkgroupVar, Aliased) {
@@ -53,7 +53,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("groupshared float wg;\n"));
+    EXPECT_THAT(gen.Result(), HasSubstr("groupshared float wg;\n"));
 }
 
 }  // namespace
diff --git a/src/tint/writer/ir_text_generator.cc b/src/tint/writer/ir_text_generator.cc
new file mode 100644
index 0000000..d467dc7
--- /dev/null
+++ b/src/tint/writer/ir_text_generator.cc
@@ -0,0 +1,29 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/writer/ir_text_generator.h"
+
+#include "src/tint/utils/map.h"
+
+namespace tint::writer {
+
+IRTextGenerator::IRTextGenerator(ir::Module* mod) : ir_(mod) {}
+
+IRTextGenerator::~IRTextGenerator() = default;
+
+std::string IRTextGenerator::UniqueIdentifier(const std::string& prefix) {
+    return ir_->symbols.New(prefix).Name();
+}
+
+}  // namespace tint::writer
diff --git a/src/tint/writer/ir_text_generator.h b/src/tint/writer/ir_text_generator.h
new file mode 100644
index 0000000..60ccfbc
--- /dev/null
+++ b/src/tint/writer/ir_text_generator.h
@@ -0,0 +1,55 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_WRITER_IR_TEXT_GENERATOR_H_
+#define SRC_TINT_WRITER_IR_TEXT_GENERATOR_H_
+
+#include <string>
+
+#include "src/tint/ir/module.h"
+#include "src/tint/writer/text_generator.h"
+
+namespace tint::writer {
+
+/// Helper methods for generators which are creating text output
+class IRTextGenerator : public TextGenerator {
+  public:
+    /// Constructor
+    /// @param mod the IR module used by the generator
+    explicit IRTextGenerator(ir::Module* mod);
+    ~IRTextGenerator() override;
+
+    /// @return a new, unique identifier with the given prefix.
+    /// @param prefix optional prefix to apply to the generated identifier. If
+    /// empty "tint_symbol" will be used.
+    std::string UniqueIdentifier(const std::string& prefix = "") override;
+
+    /// @returns the generated shader string
+    std::string Result() const override {
+        utils::StringStream ss;
+        ss << preamble_buffer_.String() << std::endl << main_buffer_.String();
+        return ss.str();
+    }
+
+  protected:
+    /// The IR module
+    ir::Module* ir_ = nullptr;
+
+    /// The buffer holding preamble text
+    TextBuffer preamble_buffer_;
+};
+
+}  // namespace tint::writer
+
+#endif  // SRC_TINT_WRITER_IR_TEXT_GENERATOR_H_
diff --git a/src/tint/writer/msl/generator.cc b/src/tint/writer/msl/generator.cc
index f811a88..14b317a 100644
--- a/src/tint/writer/msl/generator.cc
+++ b/src/tint/writer/msl/generator.cc
@@ -18,6 +18,11 @@
 
 #include "src/tint/writer/msl/generator_impl.h"
 
+#if TINT_BUILD_IR
+#include "src/tint/ir/from_program.h"                  // nogncheck
+#include "src/tint/writer/msl/ir/generator_impl_ir.h"  // nogncheck
+#endif                                                 // TINT_BUILD_IR
+
 namespace tint::writer::msl {
 
 Options::Options() = default;
@@ -36,24 +41,43 @@
         return result;
     }
 
-    // Sanitize the program.
-    auto sanitized_result = Sanitize(program, options);
-    if (!sanitized_result.program.IsValid()) {
-        result.success = false;
-        result.error = sanitized_result.program.Diagnostics().str();
-        return result;
-    }
-    result.needs_storage_buffer_sizes = sanitized_result.needs_storage_buffer_sizes;
-    result.used_array_length_from_uniform_indices =
-        std::move(sanitized_result.used_array_length_from_uniform_indices);
+#if TINT_BUILD_IR
+    if (options.use_tint_ir) {
+        // Convert the AST program to an IR module.
+        auto converted = ir::FromProgram(program);
+        if (!converted) {
+            result.error = "IR converter: " + converted.Failure();
+            return result;
+        }
 
-    // Generate the MSL code.
-    auto impl = std::make_unique<GeneratorImpl>(&sanitized_result.program);
-    result.success = impl->Generate();
-    result.error = impl->Diagnostics().str();
-    result.msl = impl->result();
-    result.has_invariant_attribute = impl->HasInvariant();
-    result.workgroup_allocations = impl->DynamicWorkgroupAllocations();
+        // Generate the MSL code.
+        auto ir = converted.Move();
+        auto impl = std::make_unique<GeneratorImplIr>(&ir);
+        result.success = impl->Generate();
+        result.error = impl->Diagnostics().str();
+        result.msl = impl->Result();
+    } else  // NOLINT(readability/braces)
+#endif
+    {
+        // Sanitize the program.
+        auto sanitized_result = Sanitize(program, options);
+        if (!sanitized_result.program.IsValid()) {
+            result.success = false;
+            result.error = sanitized_result.program.Diagnostics().str();
+            return result;
+        }
+        result.needs_storage_buffer_sizes = sanitized_result.needs_storage_buffer_sizes;
+        result.used_array_length_from_uniform_indices =
+            std::move(sanitized_result.used_array_length_from_uniform_indices);
+
+        // Generate the MSL code.
+        auto impl = std::make_unique<GeneratorImpl>(&sanitized_result.program);
+        result.success = impl->Generate();
+        result.error = impl->Diagnostics().str();
+        result.msl = impl->Result();
+        result.has_invariant_attribute = impl->HasInvariant();
+        result.workgroup_allocations = impl->DynamicWorkgroupAllocations();
+    }
 
     return result;
 }
diff --git a/src/tint/writer/msl/generator.h b/src/tint/writer/msl/generator.h
index 53805f1..886277c 100644
--- a/src/tint/writer/msl/generator.h
+++ b/src/tint/writer/msl/generator.h
@@ -74,6 +74,11 @@
     /// Options used in the bindings remapper
     BindingRemapperOptions binding_remapper_options = {};
 
+#if TINT_BUILD_IR
+    /// Set to `true` to generate MSL via the Tint IR instead of from the AST.
+    bool use_tint_ir = false;
+#endif
+
     /// Reflect the fields of this class so that it can be used by tint::ForeachField()
     TINT_REFLECT(disable_robustness,
                  buffer_size_ubo_index,
diff --git a/src/tint/writer/msl/generator_impl.cc b/src/tint/writer/msl/generator_impl.cc
index 3cf5b31..4aabeef 100644
--- a/src/tint/writer/msl/generator_impl.cc
+++ b/src/tint/writer/msl/generator_impl.cc
@@ -85,7 +85,7 @@
 #include "src/tint/utils/scoped_assignment.h"
 #include "src/tint/utils/string_stream.h"
 #include "src/tint/writer/check_supported_extensions.h"
-#include "src/tint/writer/float_to_string.h"
+#include "src/tint/writer/msl/generator_support.h"
 
 namespace tint::writer::msl {
 namespace {
@@ -94,45 +94,6 @@
     return utils::IsAnyOf<ast::BreakStatement>(stmts->Last());
 }
 
-void PrintF32(utils::StringStream& out, float value) {
-    // Note: Currently inf and nan should not be constructable, but this is implemented for the day
-    // we support them.
-    if (std::isinf(value)) {
-        out << (value >= 0 ? "INFINITY" : "-INFINITY");
-    } else if (std::isnan(value)) {
-        out << "NAN";
-    } else {
-        out << FloatToString(value) << "f";
-    }
-}
-
-void PrintF16(utils::StringStream& out, float value) {
-    // Note: Currently inf and nan should not be constructable, but this is implemented for the day
-    // we support them.
-    if (std::isinf(value)) {
-        // HUGE_VALH evaluates to +infinity.
-        out << (value >= 0 ? "HUGE_VALH" : "-HUGE_VALH");
-    } else if (std::isnan(value)) {
-        // There is no NaN expr for half in MSL, "NAN" is of float type.
-        out << "NAN";
-    } else {
-        out << FloatToString(value) << "h";
-    }
-}
-
-void PrintI32(utils::StringStream& out, int32_t value) {
-    // MSL (and C++) parse `-2147483648` as a `long` because it parses unary minus and `2147483648`
-    // as separate tokens, and the latter doesn't fit into an (32-bit) `int`.
-    // WGSL, on the other hand, parses this as an `i32`.
-    // To avoid issues with `long` to `int` casts, emit `(-2147483647 - 1)` instead, which ensures
-    // the expression type is `int`.
-    if (auto int_min = std::numeric_limits<int32_t>::min(); value == int_min) {
-        out << "(" << int_min + 1 << " - 1)";
-    } else {
-        out << value;
-    }
-}
-
 class ScopedBitCast {
   public:
     ScopedBitCast(GeneratorImpl* generator,
@@ -150,7 +111,7 @@
 
         // Bit cast
         s << "as_type<";
-        generator->EmitType(s, target_type, "");
+        generator->EmitType(s, target_type);
         s << ">(";
     }
 
@@ -287,9 +248,9 @@
         return false;
     }
 
-    line() << "#include <metal_stdlib>";
-    line();
-    line() << "using namespace metal;";
+    Line() << "#include <metal_stdlib>";
+    Line();
+    Line() << "using namespace metal;";
 
     auto helpers_insertion_point = current_buffer_->lines.size();
 
@@ -298,7 +259,7 @@
         bool ok = Switch(
             decl,  //
             [&](const ast::Struct* str) {
-                TINT_DEFER(line());
+                TINT_DEFER(Line());
                 return EmitTypeDecl(TypeOf(str));
             },
             [&](const ast::Alias*) {
@@ -315,7 +276,7 @@
                 return false;
             },
             [&](const ast::Function* func) {
-                TINT_DEFER(line());
+                TINT_DEFER(Line());
                 if (func->IsEntryPoint()) {
                     return EmitEntryPointFunction(func);
                 }
@@ -346,12 +307,12 @@
         // 'invariant' attribute requires MSL 2.1 or higher.
         // WGSL can ignore the invariant attribute on pre MSL 2.1 devices.
         // See: https://github.com/gpuweb/gpuweb/issues/893#issuecomment-745537465
-        line(&helpers_) << "#if __METAL_VERSION__ >= 210";
-        line(&helpers_) << "#define " << invariant_define_name_ << " [[invariant]]";
-        line(&helpers_) << "#else";
-        line(&helpers_) << "#define " << invariant_define_name_;
-        line(&helpers_) << "#endif";
-        line(&helpers_);
+        Line(&helpers_) << "#if __METAL_VERSION__ >= 210";
+        Line(&helpers_) << "#define " << invariant_define_name_ << " [[invariant]]";
+        Line(&helpers_) << "#else";
+        Line(&helpers_) << "#define " << invariant_define_name_;
+        Line(&helpers_) << "#endif";
+        Line(&helpers_);
     }
 
     if (!helpers_.lines.empty()) {
@@ -403,7 +364,7 @@
 
 bool GeneratorImpl::EmitBitcast(utils::StringStream& out, const ast::BitcastExpression* expr) {
     out << "as_type<";
-    if (!EmitType(out, TypeOf(expr)->UnwrapRef(), "")) {
+    if (!EmitType(out, TypeOf(expr)->UnwrapRef())) {
         return false;
     }
 
@@ -417,7 +378,7 @@
 }
 
 bool GeneratorImpl::EmitAssign(const ast::AssignmentStatement* stmt) {
-    auto out = line();
+    auto out = Line();
 
     if (!EmitExpression(out, stmt->lhs)) {
         return false;
@@ -629,12 +590,12 @@
 }
 
 bool GeneratorImpl::EmitBreak(const ast::BreakStatement*) {
-    line() << "break;";
+    Line() << "break;";
     return true;
 }
 
 bool GeneratorImpl::EmitBreakIf(const ast::BreakIfStatement* b) {
-    auto out = line();
+    auto out = Line();
     out << "if (";
     if (!EmitExpression(out, b->condition)) {
         return false;
@@ -795,7 +756,7 @@
 bool GeneratorImpl::EmitTypeConversion(utils::StringStream& out,
                                        const sem::Call* call,
                                        const sem::ValueConversion* conv) {
-    if (!EmitType(out, conv->Target(), "")) {
+    if (!EmitType(out, conv->Target())) {
         return false;
     }
     out << "(";
@@ -819,7 +780,7 @@
     bool ok = Switch(
         type,
         [&](const type::Array*) {
-            if (!EmitType(out, type, "")) {
+            if (!EmitType(out, type)) {
                 return false;
             }
             out << "{";
@@ -832,7 +793,7 @@
             return true;
         },
         [&](Default) {
-            if (!EmitType(out, type, "")) {
+            if (!EmitType(out, type)) {
                 return false;
             }
             out << "(";
@@ -935,7 +896,7 @@
                     auto* arg_ty = builtin->Parameters()[1]->Type();
 
                     {
-                        auto f = line(&buf);
+                        auto f = Line(&buf);
                         auto str_name = StructName(builtin->ReturnType()->As<type::Struct>());
                         f << str_name << " " << name << "(";
                         if (!EmitTypeAndName(f, atomic_ty, "atomic")) {
@@ -955,22 +916,22 @@
                     buf.IncrementIndent();
                     TINT_DEFER({
                         buf.DecrementIndent();
-                        line(&buf) << "}";
-                        line(&buf);
+                        Line(&buf) << "}";
+                        Line(&buf);
                     });
 
                     {
-                        auto f = line(&buf);
+                        auto f = Line(&buf);
                         if (!EmitTypeAndName(f, arg_ty, "old_value")) {
                             return "";
                         }
                         f << " = compare;";
                     }
-                    line(&buf) << "bool exchanged = "
+                    Line(&buf) << "bool exchanged = "
                                   "atomic_compare_exchange_weak_explicit(atomic, "
                                   "&old_value, value, memory_order_relaxed, "
                                   "memory_order_relaxed);";
-                    line(&buf) << "return {old_value, exchanged};";
+                    Line(&buf) << "return {old_value, exchanged};";
                     return name;
                 });
 
@@ -1074,7 +1035,7 @@
             if (dims.size() == 1) {
                 get_dim(dims[0]);
             } else {
-                EmitType(out, TypeOf(expr)->UnwrapRef(), "");
+                EmitType(out, TypeOf(expr)->UnwrapRef());
                 out << "(";
                 for (size_t i = 0; i < dims.size(); i++) {
                     if (i > 0) {
@@ -1315,10 +1276,10 @@
             auto fn_name = UniqueIdentifier("tint_dot" + std::to_string(vec_ty->Width()));
             auto v = "vec<T," + std::to_string(vec_ty->Width()) + ">";
 
-            line(&b) << "template<typename T>";
-            line(&b) << "T " << fn_name << "(" << v << " a, " << v << " b) {";
+            Line(&b) << "template<typename T>";
+            Line(&b) << "T " << fn_name << "(" << v << " a, " << v << " b) {";
             {
-                auto l = line(&b);
+                auto l = Line(&b);
                 l << "  return ";
                 for (uint32_t i = 0; i < vec_ty->Width(); i++) {
                     if (i > 0) {
@@ -1328,7 +1289,7 @@
                 }
                 l << ";";
             }
-            line(&b) << "}";
+            Line(&b) << "}";
             return fn_name;
         });
     }
@@ -1364,9 +1325,9 @@
                 return false;
             }
 
-            line(b) << StructName(builtin->ReturnType()->As<type::Struct>()) << " result;";
-            line(b) << "result.fract = modf(" << in << ", result.whole);";
-            line(b) << "return result;";
+            Line(b) << StructName(builtin->ReturnType()->As<type::Struct>()) << " result;";
+            Line(b) << "result.fract = modf(" << in << ", result.whole);";
+            Line(b) << "return result;";
             return true;
         });
 }
@@ -1390,9 +1351,9 @@
                 return false;
             }
 
-            line(b) << StructName(builtin->ReturnType()->As<type::Struct>()) << " result;";
-            line(b) << "result.fract = frexp(" << in << ", result.exp);";
-            line(b) << "return result;";
+            Line(b) << StructName(builtin->ReturnType()->As<type::Struct>()) << " result;";
+            Line(b) << "result.fract = frexp(" << in << ", result.exp);";
+            Line(b) << "return result;";
             return true;
         });
 }
@@ -1402,7 +1363,7 @@
                                     const sem::Builtin* builtin) {
     return CallBuiltinHelper(out, expr, builtin,
                              [&](TextBuffer* b, const std::vector<std::string>& params) {
-                                 line(b) << "return " << params[0] << " * " << std::setprecision(20)
+                                 Line(b) << "return " << params[0] << " * " << std::setprecision(20)
                                          << sem::kRadToDeg << ";";
                                  return true;
                              });
@@ -1413,7 +1374,7 @@
                                     const sem::Builtin* builtin) {
     return CallBuiltinHelper(out, expr, builtin,
                              [&](TextBuffer* b, const std::vector<std::string>& params) {
-                                 line(b) << "return " << params[0] << " * " << std::setprecision(20)
+                                 Line(b) << "return " << params[0] << " * " << std::setprecision(20)
                                          << sem::kDegToRad << ";";
                                  return true;
                              });
@@ -1576,7 +1537,7 @@
 bool GeneratorImpl::EmitCase(const ast::CaseStatement* stmt) {
     auto* sem = builder_.Sem().Get<sem::CaseStatement>(stmt);
     for (auto* selector : sem->Selectors()) {
-        auto out = line();
+        auto out = Line();
 
         if (selector->IsDefault()) {
             out << "default";
@@ -1602,11 +1563,11 @@
         }
 
         if (!last_is_break(stmt->body)) {
-            line() << "break;";
+            Line() << "break;";
         }
     }
 
-    line() << "}";
+    Line() << "}";
 
     return true;
 }
@@ -1616,7 +1577,7 @@
         return false;
     }
 
-    line() << "continue;";
+    Line() << "continue;";
     return true;
 }
 
@@ -1647,7 +1608,7 @@
             return EmitZeroValue(out, vec->type());
         },
         [&](const type::Matrix* mat) {
-            if (!EmitType(out, mat, "")) {
+            if (!EmitType(out, mat)) {
                 return false;
             }
             ScopedParen sp(out);
@@ -1692,7 +1653,7 @@
             return true;
         },
         [&](const type::Vector* v) {
-            if (!EmitType(out, v, "")) {
+            if (!EmitType(out, v)) {
                 return false;
             }
 
@@ -1716,7 +1677,7 @@
             return true;
         },
         [&](const type::Matrix* m) {
-            if (!EmitType(out, m, "")) {
+            if (!EmitType(out, m)) {
                 return false;
             }
 
@@ -1733,7 +1694,7 @@
             return true;
         },
         [&](const type::Array* a) {
-            if (!EmitType(out, a, "")) {
+            if (!EmitType(out, a)) {
                 return false;
             }
 
@@ -1874,8 +1835,8 @@
     auto* func_sem = program_->Sem().Get(func);
 
     {
-        auto out = line();
-        if (!EmitType(out, func_sem->ReturnType(), "")) {
+        auto out = Line();
+        if (!EmitType(out, func_sem->ReturnType())) {
             return false;
         }
         out << " " << func->name->symbol.Name() << "(";
@@ -1889,14 +1850,13 @@
 
             auto* type = program_->Sem().Get(v)->Type();
 
-            std::string param_name = "const " + v->name->symbol.Name();
-            if (!EmitType(out, type, param_name)) {
+            if (!EmitType(out, type)) {
                 return false;
             }
-            // Parameter name is output as part of the type for pointers.
-            if (!type->Is<type::Pointer>()) {
-                out << " " << v->name->symbol.Name();
+            if (type->Is<type::Pointer>()) {
+                out << " const";
             }
+            out << " " << v->name->symbol.Name();
         }
 
         out << ") {";
@@ -1906,78 +1866,11 @@
         return false;
     }
 
-    line() << "}";
+    Line() << "}";
 
     return true;
 }
 
-std::string GeneratorImpl::builtin_to_attribute(builtin::BuiltinValue builtin) const {
-    switch (builtin) {
-        case builtin::BuiltinValue::kPosition:
-            return "position";
-        case builtin::BuiltinValue::kVertexIndex:
-            return "vertex_id";
-        case builtin::BuiltinValue::kInstanceIndex:
-            return "instance_id";
-        case builtin::BuiltinValue::kFrontFacing:
-            return "front_facing";
-        case builtin::BuiltinValue::kFragDepth:
-            return "depth(any)";
-        case builtin::BuiltinValue::kLocalInvocationId:
-            return "thread_position_in_threadgroup";
-        case builtin::BuiltinValue::kLocalInvocationIndex:
-            return "thread_index_in_threadgroup";
-        case builtin::BuiltinValue::kGlobalInvocationId:
-            return "thread_position_in_grid";
-        case builtin::BuiltinValue::kWorkgroupId:
-            return "threadgroup_position_in_grid";
-        case builtin::BuiltinValue::kNumWorkgroups:
-            return "threadgroups_per_grid";
-        case builtin::BuiltinValue::kSampleIndex:
-            return "sample_id";
-        case builtin::BuiltinValue::kSampleMask:
-            return "sample_mask";
-        case builtin::BuiltinValue::kPointSize:
-            return "point_size";
-        default:
-            break;
-    }
-    return "";
-}
-
-std::string GeneratorImpl::interpolation_to_attribute(
-    builtin::InterpolationType type,
-    builtin::InterpolationSampling sampling) const {
-    std::string attr;
-    switch (sampling) {
-        case builtin::InterpolationSampling::kCenter:
-            attr = "center_";
-            break;
-        case builtin::InterpolationSampling::kCentroid:
-            attr = "centroid_";
-            break;
-        case builtin::InterpolationSampling::kSample:
-            attr = "sample_";
-            break;
-        case builtin::InterpolationSampling::kUndefined:
-            break;
-    }
-    switch (type) {
-        case builtin::InterpolationType::kPerspective:
-            attr += "perspective";
-            break;
-        case builtin::InterpolationType::kLinear:
-            attr += "no_perspective";
-            break;
-        case builtin::InterpolationType::kFlat:
-            attr += "flat";
-            break;
-        case builtin::InterpolationType::kUndefined:
-            break;
-    }
-    return attr;
-}
-
 bool GeneratorImpl::EmitEntryPointFunction(const ast::Function* func) {
     auto* func_sem = builder_.Sem().Get(func);
 
@@ -2003,7 +1896,7 @@
     };
 
     {
-        auto out = line();
+        auto out = Line();
 
         EmitStage(out, func->PipelineStage());
         out << " ";
@@ -2022,14 +1915,10 @@
 
             auto* type = program_->Sem().Get(param)->Type()->UnwrapRef();
 
-            auto param_name = param->name->symbol.Name();
-            if (!EmitType(out, type, param_name)) {
+            if (!EmitType(out, type)) {
                 return false;
             }
-            // Parameter name is output as part of the type for pointers.
-            if (!type->Is<type::Pointer>()) {
-                out << " " << param_name;
-            }
+            out << " " << param->name->symbol.Name();
 
             bool ok = Switch(
                 type,  //
@@ -2091,7 +1980,7 @@
 
                         builtin_found = true;
 
-                        auto name = builtin_to_attribute(builtin);
+                        auto name = BuiltinToAttribute(builtin);
                         if (name.empty()) {
                             diagnostics_.add_error(diag::System::Writer, "unknown builtin");
                             return false;
@@ -2126,7 +2015,7 @@
         }
     }
 
-    line() << "}";
+    Line() << "}";
     return true;
 }
 
@@ -2147,7 +2036,7 @@
     };
 
     TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
-    line() << "while (true) {";
+    Line() << "while (true) {";
     {
         ScopedIndent si(this);
         if (!EmitStatements(stmt->body->statements)) {
@@ -2157,7 +2046,7 @@
             return false;
         }
     }
-    line() << "}";
+    Line() << "}";
 
     return true;
 }
@@ -2198,15 +2087,15 @@
     // statement(s) before the loop in a new block.
     bool nest_in_block = init_buf.lines.size() > 1 || (stmt->initializer && emit_as_loop);
     if (nest_in_block) {
-        line() << "{";
-        increment_indent();
+        Line() << "{";
+        IncrementIndent();
         current_buffer_->Append(init_buf);
         init_buf.lines.clear();  // Don't emit the initializer again in the 'for'
     }
     TINT_DEFER({
         if (nest_in_block) {
-            decrement_indent();
-            line() << "}";
+            DecrementIndent();
+            Line() << "}";
         }
     });
 
@@ -2217,16 +2106,16 @@
         };
 
         TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
-        line() << "while (true) {";
-        increment_indent();
+        Line() << "while (true) {";
+        IncrementIndent();
         TINT_DEFER({
-            decrement_indent();
-            line() << "}";
+            DecrementIndent();
+            Line() << "}";
         });
 
         if (stmt->condition) {
             current_buffer_->Append(cond_pre);
-            line() << "if (!(" << cond_buf.str() << ")) { break; }";
+            Line() << "if (!(" << cond_buf.str() << ")) { break; }";
         }
 
         if (!EmitStatements(stmt->body->statements)) {
@@ -2239,7 +2128,7 @@
     } else {
         // For-loop can be generated.
         {
-            auto out = line();
+            auto out = Line();
             out << "for";
             {
                 ScopedParen sp(out);
@@ -2265,7 +2154,7 @@
                 return false;
             }
         }
-        line() << "}";
+        Line() << "}";
     }
 
     return true;
@@ -2290,22 +2179,22 @@
     // as a regular while in MSL. Instead we need to generate a `while(true)` loop.
     bool emit_as_loop = cond_pre.lines.size() > 0;
     if (emit_as_loop) {
-        line() << "while (true) {";
-        increment_indent();
+        Line() << "while (true) {";
+        IncrementIndent();
         TINT_DEFER({
-            decrement_indent();
-            line() << "}";
+            DecrementIndent();
+            Line() << "}";
         });
 
         current_buffer_->Append(cond_pre);
-        line() << "if (!(" << cond_buf.str() << ")) { break; }";
+        Line() << "if (!(" << cond_buf.str() << ")) { break; }";
         if (!EmitStatements(stmt->body->statements)) {
             return false;
         }
     } else {
         // While can be generated.
         {
-            auto out = line();
+            auto out = Line();
             out << "while";
             {
                 ScopedParen sp(out);
@@ -2316,7 +2205,7 @@
         if (!EmitStatementsWithIndent(stmt->body->statements)) {
             return false;
         }
-        line() << "}";
+        Line() << "}";
     }
     return true;
 }
@@ -2324,13 +2213,13 @@
 bool GeneratorImpl::EmitDiscard(const ast::DiscardStatement*) {
     // TODO(dsinclair): Verify this is correct when the discard semantics are
     // defined for WGSL (https://github.com/gpuweb/gpuweb/issues/361)
-    line() << "discard_fragment();";
+    Line() << "discard_fragment();";
     return true;
 }
 
 bool GeneratorImpl::EmitIf(const ast::IfStatement* stmt) {
     {
-        auto out = line();
+        auto out = Line();
         out << "if (";
         if (!EmitExpression(out, stmt->condition)) {
             return false;
@@ -2343,7 +2232,7 @@
     }
 
     if (stmt->else_statement) {
-        line() << "} else {";
+        Line() << "} else {";
         if (auto* block = stmt->else_statement->As<ast::BlockStatement>()) {
             if (!EmitStatementsWithIndent(block->statements)) {
                 return false;
@@ -2354,7 +2243,7 @@
             }
         }
     }
-    line() << "}";
+    Line() << "}";
 
     return true;
 }
@@ -2413,7 +2302,7 @@
 }
 
 bool GeneratorImpl::EmitReturn(const ast::ReturnStatement* stmt) {
-    auto out = line();
+    auto out = Line();
     out << "return";
     if (stmt->value) {
         out << " ";
@@ -2426,13 +2315,13 @@
 }
 
 bool GeneratorImpl::EmitBlock(const ast::BlockStatement* stmt) {
-    line() << "{";
+    Line() << "{";
 
     if (!EmitStatementsWithIndent(stmt->statements)) {
         return false;
     }
 
-    line() << "}";
+    Line() << "}";
 
     return true;
 }
@@ -2453,7 +2342,7 @@
             return EmitBreakIf(b);
         },
         [&](const ast::CallStatement* c) {  //
-            auto out = line();
+            auto out = Line();
             if (!EmitCall(out, c->expr)) {  //
                 return false;
             }
@@ -2524,7 +2413,7 @@
 
 bool GeneratorImpl::EmitSwitch(const ast::SwitchStatement* stmt) {
     {
-        auto out = line();
+        auto out = Line();
         out << "switch(";
         if (!EmitExpression(out, stmt->condition)) {
             return false;
@@ -2541,19 +2430,12 @@
         }
     }
 
-    line() << "}";
+    Line() << "}";
 
     return true;
 }
 
-bool GeneratorImpl::EmitType(utils::StringStream& out,
-                             const type::Type* type,
-                             const std::string& name,
-                             bool* name_printed /* = nullptr */) {
-    if (name_printed) {
-        *name_printed = false;
-    }
-
+bool GeneratorImpl::EmitType(utils::StringStream& out, const type::Type* type) {
     return Switch(
         type,
         [&](const type::Atomic* atomic) {
@@ -2571,7 +2453,7 @@
         },
         [&](const type::Array* arr) {
             out << ArrayType() << "<";
-            if (!EmitType(out, arr->ElemType(), "")) {
+            if (!EmitType(out, arr->ElemType())) {
                 return false;
             }
             out << ", ";
@@ -2607,7 +2489,7 @@
             return true;
         },
         [&](const type::Matrix* mat) {
-            if (!EmitType(out, mat->type(), "")) {
+            if (!EmitType(out, mat->type())) {
                 return false;
             }
             out << mat->columns() << "x" << mat->rows();
@@ -2621,13 +2503,10 @@
                 return false;
             }
             out << " ";
-            if (!EmitType(out, ptr->StoreType(), "")) {
+            if (!EmitType(out, ptr->StoreType())) {
                 return false;
             }
-            out << "* " << name;
-            if (name_printed) {
-                *name_printed = true;
-            }
+            out << "*";
             return true;
         },
         [&](const type::Sampler*) {
@@ -2693,7 +2572,7 @@
                     return true;
                 },
                 [&](const type::StorageTexture* storage) {
-                    if (!EmitType(out, storage->type(), "")) {
+                    if (!EmitType(out, storage->type())) {
                         return false;
                     }
 
@@ -2710,14 +2589,14 @@
                     return true;
                 },
                 [&](const type::MultisampledTexture* ms) {
-                    if (!EmitType(out, ms->type(), "")) {
+                    if (!EmitType(out, ms->type())) {
                         return false;
                     }
                     out << ", access::read";
                     return true;
                 },
                 [&](const type::SampledTexture* sampled) {
-                    if (!EmitType(out, sampled->type(), "")) {
+                    if (!EmitType(out, sampled->type())) {
                         return false;
                     }
                     out << ", access::sample";
@@ -2736,7 +2615,7 @@
             if (vec->Packed()) {
                 out << "packed_";
             }
-            if (!EmitType(out, vec->type(), "")) {
+            if (!EmitType(out, vec->type())) {
                 return false;
             }
             out << vec->Width();
@@ -2756,13 +2635,10 @@
 bool GeneratorImpl::EmitTypeAndName(utils::StringStream& out,
                                     const type::Type* type,
                                     const std::string& name) {
-    bool name_printed = false;
-    if (!EmitType(out, type, name, &name_printed)) {
+    if (!EmitType(out, type)) {
         return false;
     }
-    if (!name_printed) {
-        out << " " << name;
-    }
+    out << " " << name;
     return true;
 }
 
@@ -2795,7 +2671,7 @@
         return true;
     }
 
-    line(b) << "struct " << StructName(str) << " {";
+    Line(b) << "struct " << StructName(str) << " {";
 
     bool is_host_shareable = str->IsHostShareable();
 
@@ -2812,7 +2688,7 @@
             name = UniqueIdentifier("tint_pad");
         } while (str->FindMember(program_->Symbols().Get(name)));
 
-        auto out = line(b);
+        auto out = Line(b);
         add_byte_offset_comment(out, msl_offset);
         out << ArrayType() << "<int8_t, " << size << "> " << name << ";";
     };
@@ -2821,7 +2697,7 @@
 
     uint32_t msl_offset = 0;
     for (auto* mem : str->Members()) {
-        auto out = line(b);
+        auto out = Line(b);
         auto mem_name = mem->Name().Name();
         auto wgsl_offset = mem->Offset();
 
@@ -2842,7 +2718,7 @@
             add_byte_offset_comment(out, msl_offset);
         }
 
-        if (!EmitType(out, mem->Type(), mem_name)) {
+        if (!EmitType(out, mem->Type())) {
             return false;
         }
 
@@ -2853,7 +2729,7 @@
         auto& attributes = mem->Attributes();
 
         if (auto builtin = attributes.builtin) {
-            auto name = builtin_to_attribute(builtin.value());
+            auto name = BuiltinToAttribute(builtin.value());
             if (name.empty()) {
                 diagnostics_.add_error(diag::System::Writer, "unknown builtin");
                 return false;
@@ -2884,7 +2760,7 @@
         }
 
         if (auto interpolation = attributes.interpolation) {
-            auto name = interpolation_to_attribute(interpolation->type, interpolation->sampling);
+            auto name = InterpolationToAttribute(interpolation->type, interpolation->sampling);
             if (name.empty()) {
                 diagnostics_.add_error(diag::System::Writer, "unknown interpolation attribute");
                 return false;
@@ -2901,7 +2777,7 @@
 
         if (is_host_shareable) {
             // Calculate new MSL offset
-            auto size_align = MslPackedTypeSizeAndAlign(ty);
+            auto size_align = MslPackedTypeSizeAndAlign(diagnostics_, ty);
             if (TINT_UNLIKELY(msl_offset % size_align.align)) {
                 TINT_ICE(Writer, diagnostics_)
                     << "Misaligned MSL structure member " << ty->FriendlyName() << " " << mem_name;
@@ -2917,7 +2793,7 @@
 
     b->DecrementIndent();
 
-    line(b) << "};";
+    Line(b) << "};";
     return true;
 }
 
@@ -2936,12 +2812,12 @@
 
             auto fn_name = UniqueIdentifier("tint_unary_minus");
             {
-                auto decl = line(&b);
+                auto decl = Line(&b);
                 if (!EmitTypeAndName(decl, expr_type, fn_name)) {
                     return "";
                 }
                 decl << "(const ";
-                if (!EmitType(decl, expr_type, "")) {
+                if (!EmitType(decl, expr_type)) {
                     return "";
                 }
                 decl << " v) {";
@@ -2951,10 +2827,10 @@
                 ScopedIndent si(&b);
                 const auto largest_negative_value =
                     std::to_string(std::numeric_limits<int32_t>::min());
-                line(&b) << "return select(-v, v, v == " << largest_negative_value << ");";
+                Line(&b) << "return select(-v, v, v == " << largest_negative_value << ");";
             }
-            line(&b) << "}";
-            line(&b);
+            Line(&b) << "}";
+            Line(&b);
             return fn_name;
         });
 
@@ -2998,7 +2874,7 @@
     auto* sem = program_->Sem().Get(var);
     auto* type = sem->Type()->UnwrapRef();
 
-    auto out = line();
+    auto out = Line();
 
     switch (sem->AddressSpace()) {
         case builtin::AddressSpace::kFunction:
@@ -3015,14 +2891,10 @@
             return false;
     }
 
-    std::string name = var->name->symbol.Name();
-    if (!EmitType(out, type, name)) {
+    if (!EmitType(out, type)) {
         return false;
     }
-    // Variable name is output as part of the type for pointers.
-    if (!type->Is<type::Pointer>()) {
-        out << " " << name;
-    }
+    out << " " << var->name->symbol.Name();
 
     if (var->initializer != nullptr) {
         out << " = ";
@@ -3046,7 +2918,7 @@
     auto* sem = program_->Sem().Get(let);
     auto* type = sem->Type();
 
-    auto out = line();
+    auto out = Line();
 
     switch (sem->AddressSpace()) {
         case builtin::AddressSpace::kFunction:
@@ -3064,15 +2936,10 @@
             return false;
     }
 
-    std::string name = "const " + let->name->symbol.Name();
-    if (!EmitType(out, type, name)) {
+    if (!EmitType(out, type)) {
         return false;
     }
-
-    // Variable name is output as part of the type for pointers.
-    if (!type->Is<type::Pointer>()) {
-        out << " " << name;
-    }
+    out << " const " << let->name->symbol.Name();
 
     out << " = ";
     if (!EmitExpression(out, let->initializer)) {
@@ -3083,122 +2950,6 @@
     return true;
 }
 
-GeneratorImpl::SizeAndAlign GeneratorImpl::MslPackedTypeSizeAndAlign(const type::Type* ty) {
-    return Switch(
-        ty,
-
-        // https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf
-        // 2.1 Scalar Data Types
-        [&](const type::U32*) {
-            return SizeAndAlign{4, 4};
-        },
-        [&](const type::I32*) {
-            return SizeAndAlign{4, 4};
-        },
-        [&](const type::F32*) {
-            return SizeAndAlign{4, 4};
-        },
-        [&](const type::F16*) {
-            return SizeAndAlign{2, 2};
-        },
-
-        [&](const type::Vector* vec) {
-            auto num_els = vec->Width();
-            auto* el_ty = vec->type();
-            SizeAndAlign el_size_align = MslPackedTypeSizeAndAlign(el_ty);
-            if (el_ty->IsAnyOf<type::U32, type::I32, type::F32, type::F16>()) {
-                // Use a packed_vec type for 3-element vectors only.
-                if (num_els == 3) {
-                    // https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf
-                    // 2.2.3 Packed Vector Types
-                    return SizeAndAlign{num_els * el_size_align.size, el_size_align.align};
-                } else {
-                    // https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf
-                    // 2.2 Vector Data Types
-                    // Vector data types are aligned to their size.
-                    return SizeAndAlign{num_els * el_size_align.size, num_els * el_size_align.size};
-                }
-            }
-            TINT_UNREACHABLE(Writer, diagnostics_)
-                << "Unhandled vector element type " << el_ty->TypeInfo().name;
-            return SizeAndAlign{};
-        },
-
-        [&](const type::Matrix* mat) {
-            // https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf
-            // 2.3 Matrix Data Types
-            auto cols = mat->columns();
-            auto rows = mat->rows();
-            auto* el_ty = mat->type();
-            // Metal only support half and float matrix.
-            if (el_ty->IsAnyOf<type::F32, type::F16>()) {
-                static constexpr SizeAndAlign table_f32[] = {
-                    /* float2x2 */ {16, 8},
-                    /* float2x3 */ {32, 16},
-                    /* float2x4 */ {32, 16},
-                    /* float3x2 */ {24, 8},
-                    /* float3x3 */ {48, 16},
-                    /* float3x4 */ {48, 16},
-                    /* float4x2 */ {32, 8},
-                    /* float4x3 */ {64, 16},
-                    /* float4x4 */ {64, 16},
-                };
-                static constexpr SizeAndAlign table_f16[] = {
-                    /* half2x2 */ {8, 4},
-                    /* half2x3 */ {16, 8},
-                    /* half2x4 */ {16, 8},
-                    /* half3x2 */ {12, 4},
-                    /* half3x3 */ {24, 8},
-                    /* half3x4 */ {24, 8},
-                    /* half4x2 */ {16, 4},
-                    /* half4x3 */ {32, 8},
-                    /* half4x4 */ {32, 8},
-                };
-                if (cols >= 2 && cols <= 4 && rows >= 2 && rows <= 4) {
-                    if (el_ty->Is<type::F32>()) {
-                        return table_f32[(3 * (cols - 2)) + (rows - 2)];
-                    } else {
-                        return table_f16[(3 * (cols - 2)) + (rows - 2)];
-                    }
-                }
-            }
-
-            TINT_UNREACHABLE(Writer, diagnostics_)
-                << "Unhandled matrix element type " << el_ty->TypeInfo().name;
-            return SizeAndAlign{};
-        },
-
-        [&](const type::Array* arr) {
-            if (TINT_UNLIKELY(!arr->IsStrideImplicit())) {
-                TINT_ICE(Writer, diagnostics_)
-                    << "arrays with explicit strides should not exist past the SPIR-V reader";
-                return SizeAndAlign{};
-            }
-            if (arr->Count()->Is<type::RuntimeArrayCount>()) {
-                return SizeAndAlign{arr->Stride(), arr->Align()};
-            }
-            if (auto count = arr->ConstantCount()) {
-                return SizeAndAlign{arr->Stride() * count.value(), arr->Align()};
-            }
-            diagnostics_.add_error(diag::System::Writer, type::Array::kErrExpectedConstantCount);
-            return SizeAndAlign{};
-        },
-
-        [&](const type::Struct* str) {
-            // TODO(crbug.com/tint/650): There's an assumption here that MSL's
-            // default structure size and alignment matches WGSL's. We need to
-            // confirm this.
-            return SizeAndAlign{str->Size(), str->Align()};
-        },
-
-        [&](const type::Atomic* atomic) { return MslPackedTypeSizeAndAlign(atomic->Type()); },
-
-        [&](Default) {
-            TINT_UNREACHABLE(Writer, diagnostics_) << "Unhandled type " << ty->TypeInfo().name;
-            return SizeAndAlign{};
-        });
-}
-
 template <typename F>
 bool GeneratorImpl::CallBuiltinHelper(utils::StringStream& out,
                                       const ast::CallExpression* call,
@@ -3212,7 +2963,7 @@
         auto fn_name = UniqueIdentifier(std::string("tint_") + builtin::str(builtin->Type()));
         std::vector<std::string> parameter_names;
         {
-            auto decl = line(&b);
+            auto decl = Line(&b);
             if (!EmitTypeAndName(decl, builtin->ReturnType(), fn_name)) {
                 return "";
             }
@@ -3237,8 +2988,8 @@
                 return "";
             }
         }
-        line(&b) << "}";
-        line(&b);
+        Line(&b) << "}";
+        Line(&b);
         return fn_name;
     });
 
@@ -3268,19 +3019,19 @@
     if (array_template_name_.empty()) {
         array_template_name_ = UniqueIdentifier("tint_array");
         auto* buf = &helpers_;
-        line(buf) << "template<typename T, size_t N>";
-        line(buf) << "struct " << array_template_name_ << " {";
-        line(buf) << "    const constant T& operator[](size_t i) const constant"
+        Line(buf) << "template<typename T, size_t N>";
+        Line(buf) << "struct " << array_template_name_ << " {";
+        Line(buf) << "    const constant T& operator[](size_t i) const constant"
                   << " { return elements[i]; }";
         for (auto* space : {"device", "thread", "threadgroup"}) {
-            line(buf) << "    " << space << " T& operator[](size_t i) " << space
+            Line(buf) << "    " << space << " T& operator[](size_t i) " << space
                       << " { return elements[i]; }";
-            line(buf) << "    const " << space << " T& operator[](size_t i) const " << space
+            Line(buf) << "    const " << space << " T& operator[](size_t i) const " << space
                       << " { return elements[i]; }";
         }
-        line(buf) << "    T elements[N];";
-        line(buf) << "};";
-        line(buf);
+        Line(buf) << "    T elements[N];";
+        Line(buf) << "};";
+        Line(buf);
     }
     return array_template_name_;
 }
diff --git a/src/tint/writer/msl/generator_impl.h b/src/tint/writer/msl/generator_impl.h
index b9bd350..42ff42b 100644
--- a/src/tint/writer/msl/generator_impl.h
+++ b/src/tint/writer/msl/generator_impl.h
@@ -85,7 +85,7 @@
     /// Constructor
     /// @param program the program to generate
     explicit GeneratorImpl(const Program* program);
-    ~GeneratorImpl();
+    ~GeneratorImpl() override;
 
     /// @returns true on successful generation; false otherwise
     bool Generate();
@@ -317,13 +317,8 @@
     /// Handles generating a type
     /// @param out the output of the type stream
     /// @param type the type to generate
-    /// @param name the name of the variable, only used for array emission
-    /// @param name_printed (optional) if not nullptr and an array was printed
     /// @returns true if the type is emitted
-    bool EmitType(utils::StringStream& out,
-                  const type::Type* type,
-                  const std::string& name,
-                  bool* name_printed = nullptr);
+    bool EmitType(utils::StringStream& out, const type::Type* type);
     /// Handles generating type and name
     /// @param out the output stream
     /// @param type the type to generate
@@ -365,25 +360,7 @@
     /// @returns the name or "" if not valid
     std::string generate_builtin_name(const sem::Builtin* builtin);
 
-    /// Converts a builtin to an attribute name
-    /// @param builtin the builtin to convert
-    /// @returns the string name of the builtin or blank on error
-    std::string builtin_to_attribute(builtin::BuiltinValue builtin) const;
-
-    /// Converts interpolation attributes to an MSL attribute
-    /// @param type the interpolation type
-    /// @param sampling the interpolation sampling
-    /// @returns the string name of the attribute or blank on error
-    std::string interpolation_to_attribute(builtin::InterpolationType type,
-                                           builtin::InterpolationSampling sampling) const;
-
   private:
-    // A pair of byte size and alignment `uint32_t`s.
-    struct SizeAndAlign {
-        uint32_t size;
-        uint32_t align;
-    };
-
     /// CallBuiltinHelper will call the builtin helper function, creating it
     /// if it hasn't been built already. If the builtin needs to be built then
     /// CallBuiltinHelper will generate the function signature and will call
@@ -409,10 +386,6 @@
 
     TextBuffer helpers_;  // Helper functions emitted at the top of the output
 
-    /// @returns the MSL packed type size and alignment in bytes for the given
-    /// type.
-    SizeAndAlign MslPackedTypeSizeAndAlign(const type::Type* ty);
-
     std::function<bool()> emit_continuing_;
 
     /// Name of atomicCompareExchangeWeak() helper for the given pointer storage
diff --git a/src/tint/writer/msl/generator_impl_assign_test.cc b/src/tint/writer/msl/generator_impl_assign_test.cc
index d73efc8..0d3523f 100644
--- a/src/tint/writer/msl/generator_impl_assign_test.cc
+++ b/src/tint/writer/msl/generator_impl_assign_test.cc
@@ -27,10 +27,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(assign)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "  lhs = rhs;\n");
+    EXPECT_EQ(gen.Result(), "  lhs = rhs;\n");
 }
 
 }  // namespace
diff --git a/src/tint/writer/msl/generator_impl_block_test.cc b/src/tint/writer/msl/generator_impl_block_test.cc
index 3733326..cbd8741 100644
--- a/src/tint/writer/msl/generator_impl_block_test.cc
+++ b/src/tint/writer/msl/generator_impl_block_test.cc
@@ -25,10 +25,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(b)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     return;
   }
 )");
@@ -40,10 +40,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitBlock(b)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     return;
   }
 )");
diff --git a/src/tint/writer/msl/generator_impl_break_test.cc b/src/tint/writer/msl/generator_impl_break_test.cc
index 85eea25..cfa1826 100644
--- a/src/tint/writer/msl/generator_impl_break_test.cc
+++ b/src/tint/writer/msl/generator_impl_break_test.cc
@@ -25,10 +25,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(b)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "  break;\n");
+    EXPECT_EQ(gen.Result(), "  break;\n");
 }
 
 }  // namespace
diff --git a/src/tint/writer/msl/generator_impl_builtin_test.cc b/src/tint/writer/msl/generator_impl_builtin_test.cc
index bb117b1..162c7f2 100644
--- a/src/tint/writer/msl/generator_impl_builtin_test.cc
+++ b/src/tint/writer/msl/generator_impl_builtin_test.cc
@@ -418,7 +418,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -450,7 +450,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -480,7 +480,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -512,7 +512,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -541,7 +541,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -565,7 +565,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -587,7 +587,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -611,7 +611,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -634,7 +634,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -666,7 +666,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -696,7 +696,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -728,7 +728,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -757,7 +757,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -781,7 +781,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -803,7 +803,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -827,7 +827,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -851,7 +851,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -876,7 +876,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -903,7 +903,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -930,7 +930,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -955,7 +955,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -980,7 +980,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -1007,7 +1007,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -1034,7 +1034,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -1082,7 +1082,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -1116,7 +1116,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 int f(int a, int b, int c) {
diff --git a/src/tint/writer/msl/generator_impl_call_test.cc b/src/tint/writer/msl/generator_impl_call_test.cc
index 17b97bc..5af9e13 100644
--- a/src/tint/writer/msl/generator_impl_call_test.cc
+++ b/src/tint/writer/msl/generator_impl_call_test.cc
@@ -75,9 +75,9 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "  my_func(param1, param2);\n");
+    EXPECT_EQ(gen.Result(), "  my_func(param1, param2);\n");
 }
 
 }  // namespace
diff --git a/src/tint/writer/msl/generator_impl_case_test.cc b/src/tint/writer/msl/generator_impl_case_test.cc
index 7306755..85e0308 100644
--- a/src/tint/writer/msl/generator_impl_case_test.cc
+++ b/src/tint/writer/msl/generator_impl_case_test.cc
@@ -28,10 +28,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitCase(s->body[0])) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  case 5: {
+    EXPECT_EQ(gen.Result(), R"(  case 5: {
     break;
   }
 )");
@@ -43,10 +43,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitCase(s->body[0])) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  case 5: {
+    EXPECT_EQ(gen.Result(), R"(  case 5: {
     break;
   }
 )");
@@ -65,10 +65,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitCase(s->body[0])) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  case 5:
+    EXPECT_EQ(gen.Result(), R"(  case 5:
   case 6: {
     break;
   }
@@ -81,10 +81,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitCase(s->body[0])) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  default: {
+    EXPECT_EQ(gen.Result(), R"(  default: {
     break;
   }
 )");
diff --git a/src/tint/writer/msl/generator_impl_const_assert_test.cc b/src/tint/writer/msl/generator_impl_const_assert_test.cc
index 13153c1..b6aa537 100644
--- a/src/tint/writer/msl/generator_impl_const_assert_test.cc
+++ b/src/tint/writer/msl/generator_impl_const_assert_test.cc
@@ -28,7 +28,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
     // const asserts are not emitted
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 )");
@@ -41,7 +41,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
     // const asserts are not emitted
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
diff --git a/src/tint/writer/msl/generator_impl_constructor_test.cc b/src/tint/writer/msl/generator_impl_constructor_test.cc
index 64c2629..3bfddc9 100644
--- a/src/tint/writer/msl/generator_impl_constructor_test.cc
+++ b/src/tint/writer/msl/generator_impl_constructor_test.cc
@@ -30,7 +30,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("false"));
+    EXPECT_THAT(gen.Result(), HasSubstr("false"));
 }
 
 TEST_F(MslGeneratorImplTest_Constructor, Int) {
@@ -39,7 +39,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("-12345"));
+    EXPECT_THAT(gen.Result(), HasSubstr("-12345"));
 }
 
 TEST_F(MslGeneratorImplTest_Constructor, UInt) {
@@ -48,7 +48,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("56779u"));
+    EXPECT_THAT(gen.Result(), HasSubstr("56779u"));
 }
 
 TEST_F(MslGeneratorImplTest_Constructor, Float) {
@@ -58,7 +58,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("1073741824.0f"));
+    EXPECT_THAT(gen.Result(), HasSubstr("1073741824.0f"));
 }
 
 TEST_F(MslGeneratorImplTest_Constructor, F16) {
@@ -70,7 +70,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("32752.0h"));
+    EXPECT_THAT(gen.Result(), HasSubstr("32752.0h"));
 }
 
 TEST_F(MslGeneratorImplTest_Constructor, Type_Float) {
@@ -79,7 +79,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("-0.00001200000042445026f"));
+    EXPECT_THAT(gen.Result(), HasSubstr("-0.00001200000042445026f"));
 }
 
 TEST_F(MslGeneratorImplTest_Constructor, Type_F16) {
@@ -90,7 +90,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("-0.0011997222900390625h"));
+    EXPECT_THAT(gen.Result(), HasSubstr("-0.0011997222900390625h"));
 }
 
 TEST_F(MslGeneratorImplTest_Constructor, Type_Bool) {
@@ -99,7 +99,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("true"));
+    EXPECT_THAT(gen.Result(), HasSubstr("true"));
 }
 
 TEST_F(MslGeneratorImplTest_Constructor, Type_Int) {
@@ -108,7 +108,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("-12345"));
+    EXPECT_THAT(gen.Result(), HasSubstr("-12345"));
 }
 
 TEST_F(MslGeneratorImplTest_Constructor, Type_Uint) {
@@ -117,7 +117,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("12345u"));
+    EXPECT_THAT(gen.Result(), HasSubstr("12345u"));
 }
 
 TEST_F(MslGeneratorImplTest_Constructor, Type_Vec_F32) {
@@ -126,7 +126,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("float3(1.0f, 2.0f, 3.0f)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("float3(1.0f, 2.0f, 3.0f)"));
 }
 
 TEST_F(MslGeneratorImplTest_Constructor, Type_Vec_F16) {
@@ -137,7 +137,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("half3(1.0h, 2.0h, 3.0h)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("half3(1.0h, 2.0h, 3.0h)"));
 }
 
 TEST_F(MslGeneratorImplTest_Constructor, Type_Vec_Empty_F32) {
@@ -146,7 +146,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("float3(0.0f)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("float3(0.0f)"));
 }
 
 TEST_F(MslGeneratorImplTest_Constructor, Type_Vec_Empty_F16) {
@@ -157,7 +157,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("half3(0.0h)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("half3(0.0h)"));
 }
 
 TEST_F(MslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_F32_Literal) {
@@ -166,7 +166,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("float3(2.0f)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("float3(2.0f)"));
 }
 
 TEST_F(MslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_F16_Literal) {
@@ -177,7 +177,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("half3(2.0h)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("half3(2.0h)"));
 }
 
 TEST_F(MslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_F32_Var) {
@@ -188,7 +188,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr(R"(float v = 2.0f;
+    EXPECT_THAT(gen.Result(), HasSubstr(R"(float v = 2.0f;
   float3 const tint_symbol = float3(v);)"));
 }
 
@@ -202,7 +202,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr(R"(half v = 2.0h;
+    EXPECT_THAT(gen.Result(), HasSubstr(R"(half v = 2.0h;
   half3 const tint_symbol = half3(v);)"));
 }
 
@@ -212,7 +212,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("bool3(true)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("bool3(true)"));
 }
 
 TEST_F(MslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_Int) {
@@ -221,7 +221,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("int3(2)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("int3(2)"));
 }
 
 TEST_F(MslGeneratorImplTest_Constructor, Type_Vec_SingleScalar_UInt) {
@@ -230,7 +230,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("uint3(2u)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("uint3(2u)"));
 }
 
 TEST_F(MslGeneratorImplTest_Constructor, Type_Mat_F32) {
@@ -241,7 +241,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_THAT(gen.result(),
+    EXPECT_THAT(gen.Result(),
                 HasSubstr("float2x3(float3(1.0f, 2.0f, 3.0f), float3(3.0f, 4.0f, 5.0f))"));
 }
 
@@ -255,7 +255,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_THAT(gen.result(),
+    EXPECT_THAT(gen.Result(),
                 HasSubstr("half2x3(half3(1.0h, 2.0h, 3.0h), half3(3.0h, 4.0h, 5.0h))"));
 }
 
@@ -281,7 +281,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_THAT(gen.result(), HasSubstr("float4x4(float4(2.0f, 3.0f, 4.0f, 8.0f), float4(0.0f), "
+    EXPECT_THAT(gen.Result(), HasSubstr("float4x4(float4(2.0f, 3.0f, 4.0f, 8.0f), float4(0.0f), "
                                         "float4(7.0f), float4(42.0f, 21.0f, 6.0f, -5.0f))"));
 }
 
@@ -309,7 +309,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_THAT(gen.result(), HasSubstr("half4x4(half4(2.0h, 3.0h, 4.0h, 8.0h), half4(0.0h), "
+    EXPECT_THAT(gen.Result(), HasSubstr("half4x4(half4(2.0h, 3.0h, 4.0h, 8.0h), half4(0.0h), "
                                         "half4(7.0h), half4(42.0h, 21.0h, 6.0h, -5.0h))"));
 }
 
@@ -320,7 +320,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_THAT(gen.result(),
+    EXPECT_THAT(gen.Result(),
                 HasSubstr("float2x3 const tint_symbol = float2x3(float3(0.0f), float3(0.0f))"));
 }
 
@@ -333,7 +333,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_THAT(gen.result(),
+    EXPECT_THAT(gen.Result(),
                 HasSubstr("half2x3 const tint_symbol = half2x3(half3(0.0h), half3(0.0h))"));
 }
 
@@ -352,7 +352,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_THAT(gen.result(), HasSubstr("float4x4 m_2 = float4x4(m_1);"));
+    EXPECT_THAT(gen.Result(), HasSubstr("float4x4 m_2 = float4x4(m_1);"));
 }
 
 TEST_F(MslGeneratorImplTest_Constructor, Type_Mat_Identity_F16) {
@@ -372,7 +372,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_THAT(gen.result(), HasSubstr("half4x4 m_2 = half4x4(m_1);"));
+    EXPECT_THAT(gen.Result(), HasSubstr("half4x4 m_2 = half4x4(m_1);"));
 }
 
 TEST_F(MslGeneratorImplTest_Constructor, Type_Array) {
@@ -383,7 +383,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("{float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f), "
+    EXPECT_THAT(gen.Result(), HasSubstr("{float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f), "
                                         "float3(7.0f, 8.0f, 9.0f)}"));
 }
 
@@ -399,7 +399,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("{.a=1, .b=2.0f, .c=int3(3, 4, 5)}"));
+    EXPECT_THAT(gen.Result(), HasSubstr("{.a=1, .b=2.0f, .c=int3(3, 4, 5)}"));
 }
 
 TEST_F(MslGeneratorImplTest_Constructor, Type_Struct_Empty) {
@@ -414,8 +414,8 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("{}"));
-    EXPECT_THAT(gen.result(), testing::Not(HasSubstr("{{}}")));
+    EXPECT_THAT(gen.Result(), HasSubstr("{}"));
+    EXPECT_THAT(gen.Result(), testing::Not(HasSubstr("{{}}")));
 }
 
 }  // namespace
diff --git a/src/tint/writer/msl/generator_impl_continue_test.cc b/src/tint/writer/msl/generator_impl_continue_test.cc
index 09b85d7..60b56cd 100644
--- a/src/tint/writer/msl/generator_impl_continue_test.cc
+++ b/src/tint/writer/msl/generator_impl_continue_test.cc
@@ -26,10 +26,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(loop)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  while (true) {
+    EXPECT_EQ(gen.Result(), R"(  while (true) {
     if (false) {
       break;
     }
diff --git a/src/tint/writer/msl/generator_impl_discard_test.cc b/src/tint/writer/msl/generator_impl_discard_test.cc
index 311401c..ae8ad38 100644
--- a/src/tint/writer/msl/generator_impl_discard_test.cc
+++ b/src/tint/writer/msl/generator_impl_discard_test.cc
@@ -27,10 +27,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "  discard_fragment();\n");
+    EXPECT_EQ(gen.Result(), "  discard_fragment();\n");
 }
 
 }  // namespace
diff --git a/src/tint/writer/msl/generator_impl_function_test.cc b/src/tint/writer/msl/generator_impl_function_test.cc
index c8020f5..d7c9ddb 100644
--- a/src/tint/writer/msl/generator_impl_function_test.cc
+++ b/src/tint/writer/msl/generator_impl_function_test.cc
@@ -32,10 +32,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  #include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(  #include <metal_stdlib>
 
   using namespace metal;
   void my_func() {
@@ -58,10 +58,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  #include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(  #include <metal_stdlib>
 
   using namespace metal;
   void my_func(float a, int b) {
@@ -78,7 +78,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 fragment void main() {
@@ -107,7 +107,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 struct tint_symbol_1 {
@@ -152,7 +152,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 struct tint_symbol {
@@ -208,7 +208,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 struct Interface {
@@ -290,7 +290,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 struct VertexOutput {
@@ -358,7 +358,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 struct Data {
@@ -397,7 +397,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 struct Data {
@@ -441,7 +441,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 struct UBO {
@@ -492,7 +492,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 struct Data {
@@ -544,7 +544,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 struct Data {
@@ -576,10 +576,10 @@
 
     GeneratorImpl& gen = SanitizeAndBuild();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  #include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(  #include <metal_stdlib>
 
   using namespace metal;
 
@@ -610,10 +610,10 @@
 
     GeneratorImpl& gen = SanitizeAndBuild();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  #include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(  #include <metal_stdlib>
 
   using namespace metal;
 
@@ -690,7 +690,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 struct Data {
diff --git a/src/tint/writer/msl/generator_impl_if_test.cc b/src/tint/writer/msl/generator_impl_if_test.cc
index acc5128..01436f8 100644
--- a/src/tint/writer/msl/generator_impl_if_test.cc
+++ b/src/tint/writer/msl/generator_impl_if_test.cc
@@ -26,10 +26,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(i)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  if (cond) {
+    EXPECT_EQ(gen.Result(), R"(  if (cond) {
     return;
   }
 )");
@@ -43,10 +43,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(i)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  if (cond) {
+    EXPECT_EQ(gen.Result(), R"(  if (cond) {
     return;
   } else {
     if (else_cond) {
@@ -63,10 +63,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(i)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  if (cond) {
+    EXPECT_EQ(gen.Result(), R"(  if (cond) {
     return;
   } else {
     return;
@@ -83,10 +83,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(i)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  if (cond) {
+    EXPECT_EQ(gen.Result(), R"(  if (cond) {
     return;
   } else {
     if (else_cond) {
diff --git a/src/tint/writer/msl/generator_impl_loop_test.cc b/src/tint/writer/msl/generator_impl_loop_test.cc
index 7146433..88b390e 100644
--- a/src/tint/writer/msl/generator_impl_loop_test.cc
+++ b/src/tint/writer/msl/generator_impl_loop_test.cc
@@ -32,10 +32,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(l)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  while (true) {
+    EXPECT_EQ(gen.Result(), R"(  while (true) {
     break;
   }
 )");
@@ -53,10 +53,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(l)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  while (true) {
+    EXPECT_EQ(gen.Result(), R"(  while (true) {
     break;
     {
       a_statement();
@@ -77,10 +77,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(l)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  while (true) {
+    EXPECT_EQ(gen.Result(), R"(  while (true) {
     break;
     {
       a_statement();
@@ -111,10 +111,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(outer)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  while (true) {
+    EXPECT_EQ(gen.Result(), R"(  while (true) {
     while (true) {
       break;
       {
@@ -151,10 +151,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(outer)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  while (true) {
+    EXPECT_EQ(gen.Result(), R"(  while (true) {
     float lhs = 2.5f;
     float other = 0.0f;
     break;
@@ -176,10 +176,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  for(; ; ) {
+    EXPECT_EQ(gen.Result(), R"(  for(; ; ) {
     return;
   }
 )");
@@ -196,10 +196,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  for(int i = 0; ; ) {
+    EXPECT_EQ(gen.Result(), R"(  for(int i = 0; ; ) {
     return;
   }
 )");
@@ -224,10 +224,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(loop)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     {
       f(1);
       f(2);
@@ -250,10 +250,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  for(; true; ) {
+    EXPECT_EQ(gen.Result(), R"(  for(; true; ) {
     return;
   }
 )");
@@ -271,10 +271,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(  for(; ; i = as_type<int>((as_type<uint>(i) + as_type<uint>(1)))) {
     return;
   }
@@ -300,10 +300,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(loop)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  while (true) {
+    EXPECT_EQ(gen.Result(), R"(  while (true) {
     return;
     {
       f(1);
@@ -326,10 +326,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(  for(int i = 0; true; i = as_type<int>((as_type<uint>(i) + as_type<uint>(1)))) {
     a_statement();
   }
@@ -356,10 +356,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(loop)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     {
       f(1);
       f(2);
@@ -386,10 +386,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  while(true) {
+    EXPECT_EQ(gen.Result(), R"(  while(true) {
     return;
   }
 )");
@@ -405,10 +405,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  while(true) {
+    EXPECT_EQ(gen.Result(), R"(  while(true) {
     continue;
   }
 )");
@@ -427,10 +427,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  while((t && false)) {
+    EXPECT_EQ(gen.Result(), R"(  while((t && false)) {
     return;
   }
 )");
diff --git a/src/tint/writer/msl/generator_impl_module_constant_test.cc b/src/tint/writer/msl/generator_impl_module_constant_test.cc
index 4f99b31..ad5a384 100644
--- a/src/tint/writer/msl/generator_impl_module_constant_test.cc
+++ b/src/tint/writer/msl/generator_impl_module_constant_test.cc
@@ -31,7 +31,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -49,7 +49,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -67,7 +67,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -85,7 +85,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -103,7 +103,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -123,7 +123,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -141,7 +141,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -159,7 +159,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -177,7 +177,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -197,7 +197,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -215,7 +215,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -233,7 +233,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -253,7 +253,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -271,7 +271,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -304,7 +304,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
diff --git a/src/tint/writer/msl/generator_impl_return_test.cc b/src/tint/writer/msl/generator_impl_return_test.cc
index 91fe996..c3478b3 100644
--- a/src/tint/writer/msl/generator_impl_return_test.cc
+++ b/src/tint/writer/msl/generator_impl_return_test.cc
@@ -27,10 +27,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(r)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "  return;\n");
+    EXPECT_EQ(gen.Result(), "  return;\n");
 }
 
 TEST_F(MslGeneratorImplTest, Emit_ReturnWithValue) {
@@ -39,10 +39,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(r)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "  return 123;\n");
+    EXPECT_EQ(gen.Result(), "  return 123;\n");
 }
 
 }  // namespace
diff --git a/src/tint/writer/msl/generator_impl_sanitizer_test.cc b/src/tint/writer/msl/generator_impl_sanitizer_test.cc
index bc211b2..e381c64 100644
--- a/src/tint/writer/msl/generator_impl_sanitizer_test.cc
+++ b/src/tint/writer/msl/generator_impl_sanitizer_test.cc
@@ -46,7 +46,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    auto got = gen.result();
+    auto got = gen.Result();
     auto* expect = R"(#include <metal_stdlib>
 
 using namespace metal;
@@ -103,7 +103,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    auto got = gen.result();
+    auto got = gen.Result();
     auto* expect = R"(#include <metal_stdlib>
 
 using namespace metal;
@@ -164,7 +164,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    auto got = gen.result();
+    auto got = gen.Result();
     auto* expect = R"(#include <metal_stdlib>
 
 using namespace metal;
@@ -224,7 +224,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    auto got = gen.result();
+    auto got = gen.Result();
     auto* expect = R"(#include <metal_stdlib>
 
 using namespace metal;
diff --git a/src/tint/writer/msl/generator_impl_switch_test.cc b/src/tint/writer/msl/generator_impl_switch_test.cc
index 352db35..4001046 100644
--- a/src/tint/writer/msl/generator_impl_switch_test.cc
+++ b/src/tint/writer/msl/generator_impl_switch_test.cc
@@ -35,10 +35,10 @@
     WrapInFunction(cond, s);
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(s)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  switch(cond) {
+    EXPECT_EQ(gen.Result(), R"(  switch(cond) {
     case 5: {
       break;
     }
@@ -59,10 +59,10 @@
     WrapInFunction(cond, s);
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(s)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  switch(cond) {
+    EXPECT_EQ(gen.Result(), R"(  switch(cond) {
     case 5:
     default: {
       break;
diff --git a/src/tint/writer/msl/generator_impl_test.cc b/src/tint/writer/msl/generator_impl_test.cc
index 41333db..fb5bd6b 100644
--- a/src/tint/writer/msl/generator_impl_test.cc
+++ b/src/tint/writer/msl/generator_impl_test.cc
@@ -51,7 +51,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 kernel void my_func() {
@@ -61,42 +61,6 @@
 )");
 }
 
-struct MslBuiltinData {
-    builtin::BuiltinValue builtin;
-    const char* attribute_name;
-};
-inline std::ostream& operator<<(std::ostream& out, MslBuiltinData data) {
-    utils::StringStream str;
-    str << data.builtin;
-    out << str.str();
-    return out;
-}
-using MslBuiltinConversionTest = TestParamHelper<MslBuiltinData>;
-TEST_P(MslBuiltinConversionTest, Emit) {
-    auto params = GetParam();
-
-    GeneratorImpl& gen = Build();
-
-    EXPECT_EQ(gen.builtin_to_attribute(params.builtin), std::string(params.attribute_name));
-}
-INSTANTIATE_TEST_SUITE_P(
-    MslGeneratorImplTest,
-    MslBuiltinConversionTest,
-    testing::Values(
-        MslBuiltinData{builtin::BuiltinValue::kPosition, "position"},
-        MslBuiltinData{builtin::BuiltinValue::kVertexIndex, "vertex_id"},
-        MslBuiltinData{builtin::BuiltinValue::kInstanceIndex, "instance_id"},
-        MslBuiltinData{builtin::BuiltinValue::kFrontFacing, "front_facing"},
-        MslBuiltinData{builtin::BuiltinValue::kFragDepth, "depth(any)"},
-        MslBuiltinData{builtin::BuiltinValue::kLocalInvocationId, "thread_position_in_threadgroup"},
-        MslBuiltinData{builtin::BuiltinValue::kLocalInvocationIndex, "thread_index_in_threadgroup"},
-        MslBuiltinData{builtin::BuiltinValue::kGlobalInvocationId, "thread_position_in_grid"},
-        MslBuiltinData{builtin::BuiltinValue::kWorkgroupId, "threadgroup_position_in_grid"},
-        MslBuiltinData{builtin::BuiltinValue::kNumWorkgroups, "threadgroups_per_grid"},
-        MslBuiltinData{builtin::BuiltinValue::kSampleIndex, "sample_id"},
-        MslBuiltinData{builtin::BuiltinValue::kSampleMask, "sample_mask"},
-        MslBuiltinData{builtin::BuiltinValue::kPointSize, "point_size"}));
-
 TEST_F(MslGeneratorImplTest, HasInvariantAttribute_True) {
     auto* out = Structure("Out", utils::Vector{
                                      Member("pos", ty.vec4<f32>(),
@@ -114,7 +78,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
     EXPECT_TRUE(gen.HasInvariant());
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -151,7 +115,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
     EXPECT_FALSE(gen.HasInvariant());
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 struct Out {
@@ -176,7 +140,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 struct tint_symbol_3 {
@@ -216,7 +180,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -277,7 +241,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 struct S1 {
@@ -365,7 +329,7 @@
     GeneratorImpl& gen = SanitizeAndBuild();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 struct tint_symbol_7 {
diff --git a/src/tint/writer/msl/generator_impl_type_test.cc b/src/tint/writer/msl/generator_impl_type_test.cc
index 05109c0..b047a24 100644
--- a/src/tint/writer/msl/generator_impl_type_test.cc
+++ b/src/tint/writer/msl/generator_impl_type_test.cc
@@ -96,7 +96,7 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type), "ary")) << gen.Diagnostics();
+    ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type))) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "tint_array<bool, 4>");
 }
 
@@ -108,7 +108,7 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type), "ary")) << gen.Diagnostics();
+    ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type))) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "tint_array<tint_array<bool, 4>, 5>");
 }
 
@@ -121,7 +121,7 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type), "ary")) << gen.Diagnostics();
+    ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type))) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "tint_array<tint_array<tint_array<bool, 4>, 5>, 6>");
 }
 
@@ -132,7 +132,7 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type), "")) << gen.Diagnostics();
+    ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type))) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "tint_array<bool, 4>");
 }
 
@@ -143,7 +143,7 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type), "ary")) << gen.Diagnostics();
+    ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type))) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "tint_array<bool, 1>");
 }
 
@@ -153,7 +153,7 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, bool_, "")) << gen.Diagnostics();
+    ASSERT_TRUE(gen.EmitType(out, bool_)) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "bool");
 }
 
@@ -163,7 +163,7 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, f32, "")) << gen.Diagnostics();
+    ASSERT_TRUE(gen.EmitType(out, f32)) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "float");
 }
 
@@ -173,7 +173,7 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, f16, "")) << gen.Diagnostics();
+    ASSERT_TRUE(gen.EmitType(out, f16)) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "half");
 }
 
@@ -183,7 +183,7 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, i32, "")) << gen.Diagnostics();
+    ASSERT_TRUE(gen.EmitType(out, i32)) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "int");
 }
 
@@ -195,7 +195,7 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, mat2x3, "")) << gen.Diagnostics();
+    ASSERT_TRUE(gen.EmitType(out, mat2x3)) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "float2x3");
 }
 
@@ -207,7 +207,7 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, mat2x3, "")) << gen.Diagnostics();
+    ASSERT_TRUE(gen.EmitType(out, mat2x3)) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "half2x3");
 }
 
@@ -219,8 +219,8 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, p, "")) << gen.Diagnostics();
-    EXPECT_EQ(out.str(), "threadgroup float* ");
+    ASSERT_TRUE(gen.EmitType(out, p)) << gen.Diagnostics();
+    EXPECT_EQ(out.str(), "threadgroup float*");
 }
 
 TEST_F(MslGeneratorImplTest, EmitType_Struct) {
@@ -232,7 +232,7 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, program->TypeOf(s), "")) << gen.Diagnostics();
+    ASSERT_TRUE(gen.EmitType(out, program->TypeOf(s))) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "S");
 }
 
@@ -713,7 +713,7 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, u32, "")) << gen.Diagnostics();
+    ASSERT_TRUE(gen.EmitType(out, u32)) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "uint");
 }
 
@@ -724,7 +724,7 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, vec3, "")) << gen.Diagnostics();
+    ASSERT_TRUE(gen.EmitType(out, vec3)) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "float3");
 }
 
@@ -734,7 +734,7 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, void_, "")) << gen.Diagnostics();
+    ASSERT_TRUE(gen.EmitType(out, void_)) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "void");
 }
 
@@ -744,7 +744,7 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, sampler, "")) << gen.Diagnostics();
+    ASSERT_TRUE(gen.EmitType(out, sampler)) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "sampler");
 }
 
@@ -754,7 +754,7 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, sampler, "")) << gen.Diagnostics();
+    ASSERT_TRUE(gen.EmitType(out, sampler)) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "sampler");
 }
 
@@ -777,7 +777,7 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, &s, "")) << gen.Diagnostics();
+    ASSERT_TRUE(gen.EmitType(out, &s)) << gen.Diagnostics();
     EXPECT_EQ(out.str(), params.result);
 }
 INSTANTIATE_TEST_SUITE_P(
@@ -798,7 +798,7 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, &s, "")) << gen.Diagnostics();
+    ASSERT_TRUE(gen.EmitType(out, &s)) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "depth2d_ms<float, access::read>");
 }
 
@@ -822,7 +822,7 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, s, "")) << gen.Diagnostics();
+    ASSERT_TRUE(gen.EmitType(out, s)) << gen.Diagnostics();
     EXPECT_EQ(out.str(), params.result);
 }
 INSTANTIATE_TEST_SUITE_P(
@@ -844,7 +844,7 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, ms, "")) << gen.Diagnostics();
+    ASSERT_TRUE(gen.EmitType(out, ms)) << gen.Diagnostics();
     EXPECT_EQ(out.str(), "texture2d_ms<uint, access::read>");
 }
 
@@ -868,7 +868,7 @@
     GeneratorImpl& gen = Build();
 
     utils::StringStream out;
-    ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type), "")) << gen.Diagnostics();
+    ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type))) << gen.Diagnostics();
     EXPECT_EQ(out.str(), params.result);
 }
 INSTANTIATE_TEST_SUITE_P(
diff --git a/src/tint/writer/msl/generator_impl_variable_decl_statement_test.cc b/src/tint/writer/msl/generator_impl_variable_decl_statement_test.cc
index be9fe72..ac318df 100644
--- a/src/tint/writer/msl/generator_impl_variable_decl_statement_test.cc
+++ b/src/tint/writer/msl/generator_impl_variable_decl_statement_test.cc
@@ -32,10 +32,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "  float a = 0.0f;\n");
+    EXPECT_EQ(gen.Result(), "  float a = 0.0f;\n");
 }
 
 TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Let) {
@@ -45,10 +45,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "  float const a = 0.0f;\n");
+    EXPECT_EQ(gen.Result(), "  float const a = 0.0f;\n");
 }
 
 TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Const) {
@@ -58,10 +58,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "");  // Not a mistake - 'const' is inlined
+    EXPECT_EQ(gen.Result(), "");  // Not a mistake - 'const' is inlined
 }
 
 TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Const_AInt) {
@@ -72,7 +72,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -90,7 +90,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -108,7 +108,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -126,7 +126,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -144,7 +144,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -164,7 +164,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -182,7 +182,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -200,7 +200,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -218,7 +218,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -238,7 +238,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -256,7 +256,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -274,7 +274,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -294,7 +294,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 void f() {
@@ -312,7 +312,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -346,7 +346,7 @@
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
 
-    EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+    EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
 
 using namespace metal;
 
@@ -376,10 +376,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "  tint_array<float, 5> a = {};\n");
+    EXPECT_EQ(gen.Result(), "  tint_array<float, 5> a = {};\n");
 }
 
 TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Struct) {
@@ -394,10 +394,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(  S a = {};
+    EXPECT_EQ(gen.Result(), R"(  S a = {};
 )");
 }
 
@@ -408,10 +408,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "  float2 a = 0.0f;\n");
+    EXPECT_EQ(gen.Result(), "  float2 a = 0.0f;\n");
 }
 
 TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Vector_f16) {
@@ -423,10 +423,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "  half2 a = 0.0h;\n");
+    EXPECT_EQ(gen.Result(), "  half2 a = 0.0h;\n");
 }
 
 TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Matrix_f32) {
@@ -437,10 +437,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "  float3x2 a = float3x2(0.0f);\n");
+    EXPECT_EQ(gen.Result(), "  float3x2 a = float3x2(0.0f);\n");
 }
 
 TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Matrix_f16) {
@@ -453,10 +453,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), "  half3x2 a = half3x2(0.0h);\n");
+    EXPECT_EQ(gen.Result(), "  half3x2 a = half3x2(0.0h);\n");
 }
 
 TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Initializer_ZeroVec_f32) {
@@ -468,7 +468,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(float3 a = float3(0.0f);
+    EXPECT_EQ(gen.Result(), R"(float3 a = float3(0.0f);
 )");
 }
 
@@ -483,7 +483,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(), R"(half3 a = half3(0.0h);
+    EXPECT_EQ(gen.Result(), R"(half3 a = half3(0.0h);
 )");
 }
 
@@ -496,7 +496,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(float2x3 a = float2x3(float3(0.0f), float3(0.0f));
 )");
 }
@@ -512,7 +512,7 @@
     GeneratorImpl& gen = Build();
 
     ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
-    EXPECT_EQ(gen.result(),
+    EXPECT_EQ(gen.Result(),
               R"(half2x3 a = half2x3(half3(0.0h), half3(0.0h));
 )");
 }
@@ -524,10 +524,10 @@
 
     GeneratorImpl& gen = SanitizeAndBuild();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr(R"(thread tint_private_vars_struct tint_private_vars = {};
+    EXPECT_THAT(gen.Result(), HasSubstr(R"(thread tint_private_vars_struct tint_private_vars = {};
     float const tint_symbol = tint_private_vars.a;
     return;
 )"));
@@ -540,10 +540,10 @@
 
     GeneratorImpl& gen = SanitizeAndBuild();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-    EXPECT_THAT(gen.result(), HasSubstr("threadgroup float tint_symbol_2;\n"));
+    EXPECT_THAT(gen.Result(), HasSubstr("threadgroup float tint_symbol_2;\n"));
 }
 
 }  // namespace
diff --git a/src/tint/writer/msl/generator_support.cc b/src/tint/writer/msl/generator_support.cc
new file mode 100644
index 0000000..4e3118b
--- /dev/null
+++ b/src/tint/writer/msl/generator_support.cc
@@ -0,0 +1,258 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/writer/msl/generator_support.h"
+
+#include <cmath>
+#include <limits>
+
+#include "src/tint/debug.h"
+#include "src/tint/switch.h"
+#include "src/tint/type/array.h"
+#include "src/tint/type/atomic.h"
+#include "src/tint/type/f16.h"
+#include "src/tint/type/f32.h"
+#include "src/tint/type/i32.h"
+#include "src/tint/type/matrix.h"
+#include "src/tint/type/struct.h"
+#include "src/tint/type/u32.h"
+#include "src/tint/type/vector.h"
+#include "src/tint/writer/float_to_string.h"
+
+namespace tint::writer::msl {
+
+std::string BuiltinToAttribute(builtin::BuiltinValue builtin) {
+    switch (builtin) {
+        case builtin::BuiltinValue::kPosition:
+            return "position";
+        case builtin::BuiltinValue::kVertexIndex:
+            return "vertex_id";
+        case builtin::BuiltinValue::kInstanceIndex:
+            return "instance_id";
+        case builtin::BuiltinValue::kFrontFacing:
+            return "front_facing";
+        case builtin::BuiltinValue::kFragDepth:
+            return "depth(any)";
+        case builtin::BuiltinValue::kLocalInvocationId:
+            return "thread_position_in_threadgroup";
+        case builtin::BuiltinValue::kLocalInvocationIndex:
+            return "thread_index_in_threadgroup";
+        case builtin::BuiltinValue::kGlobalInvocationId:
+            return "thread_position_in_grid";
+        case builtin::BuiltinValue::kWorkgroupId:
+            return "threadgroup_position_in_grid";
+        case builtin::BuiltinValue::kNumWorkgroups:
+            return "threadgroups_per_grid";
+        case builtin::BuiltinValue::kSampleIndex:
+            return "sample_id";
+        case builtin::BuiltinValue::kSampleMask:
+            return "sample_mask";
+        case builtin::BuiltinValue::kPointSize:
+            return "point_size";
+        default:
+            break;
+    }
+    return "";
+}
+
+std::string InterpolationToAttribute(builtin::InterpolationType type,
+                                     builtin::InterpolationSampling sampling) {
+    std::string attr;
+    switch (sampling) {
+        case builtin::InterpolationSampling::kCenter:
+            attr = "center_";
+            break;
+        case builtin::InterpolationSampling::kCentroid:
+            attr = "centroid_";
+            break;
+        case builtin::InterpolationSampling::kSample:
+            attr = "sample_";
+            break;
+        case builtin::InterpolationSampling::kUndefined:
+            break;
+    }
+    switch (type) {
+        case builtin::InterpolationType::kPerspective:
+            attr += "perspective";
+            break;
+        case builtin::InterpolationType::kLinear:
+            attr += "no_perspective";
+            break;
+        case builtin::InterpolationType::kFlat:
+            attr += "flat";
+            break;
+        case builtin::InterpolationType::kUndefined:
+            break;
+    }
+    return attr;
+}
+
+SizeAndAlign MslPackedTypeSizeAndAlign(diag::List diagnostics, const type::Type* ty) {
+    return tint::Switch(
+        ty,
+
+        // https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf
+        // 2.1 Scalar Data Types
+        [&](const type::U32*) {
+            return SizeAndAlign{4, 4};
+        },
+        [&](const type::I32*) {
+            return SizeAndAlign{4, 4};
+        },
+        [&](const type::F32*) {
+            return SizeAndAlign{4, 4};
+        },
+        [&](const type::F16*) {
+            return SizeAndAlign{2, 2};
+        },
+
+        [&](const type::Vector* vec) {
+            auto num_els = vec->Width();
+            auto* el_ty = vec->type();
+            SizeAndAlign el_size_align = MslPackedTypeSizeAndAlign(diagnostics, el_ty);
+            if (el_ty->IsAnyOf<type::U32, type::I32, type::F32, type::F16>()) {
+                // Use a packed_vec type for 3-element vectors only.
+                if (num_els == 3) {
+                    // https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf
+                    // 2.2.3 Packed Vector Types
+                    return SizeAndAlign{num_els * el_size_align.size, el_size_align.align};
+                } else {
+                    // https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf
+                    // 2.2 Vector Data Types
+                    // Vector data types are aligned to their size.
+                    return SizeAndAlign{num_els * el_size_align.size, num_els * el_size_align.size};
+                }
+            }
+            TINT_UNREACHABLE(Writer, diagnostics)
+                << "Unhandled vector element type " << el_ty->TypeInfo().name;
+            return SizeAndAlign{};
+        },
+
+        [&](const type::Matrix* mat) {
+            // https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf
+            // 2.3 Matrix Data Types
+            auto cols = mat->columns();
+            auto rows = mat->rows();
+            auto* el_ty = mat->type();
+            // Metal only support half and float matrix.
+            if (el_ty->IsAnyOf<type::F32, type::F16>()) {
+                static constexpr SizeAndAlign table_f32[] = {
+                    /* float2x2 */ {16, 8},
+                    /* float2x3 */ {32, 16},
+                    /* float2x4 */ {32, 16},
+                    /* float3x2 */ {24, 8},
+                    /* float3x3 */ {48, 16},
+                    /* float3x4 */ {48, 16},
+                    /* float4x2 */ {32, 8},
+                    /* float4x3 */ {64, 16},
+                    /* float4x4 */ {64, 16},
+                };
+                static constexpr SizeAndAlign table_f16[] = {
+                    /* half2x2 */ {8, 4},
+                    /* half2x3 */ {16, 8},
+                    /* half2x4 */ {16, 8},
+                    /* half3x2 */ {12, 4},
+                    /* half3x3 */ {24, 8},
+                    /* half3x4 */ {24, 8},
+                    /* half4x2 */ {16, 4},
+                    /* half4x3 */ {32, 8},
+                    /* half4x4 */ {32, 8},
+                };
+                if (cols >= 2 && cols <= 4 && rows >= 2 && rows <= 4) {
+                    if (el_ty->Is<type::F32>()) {
+                        return table_f32[(3 * (cols - 2)) + (rows - 2)];
+                    } else {
+                        return table_f16[(3 * (cols - 2)) + (rows - 2)];
+                    }
+                }
+            }
+
+            TINT_UNREACHABLE(Writer, diagnostics)
+                << "Unhandled matrix element type " << el_ty->TypeInfo().name;
+            return SizeAndAlign{};
+        },
+
+        [&](const type::Array* arr) {
+            if (TINT_UNLIKELY(!arr->IsStrideImplicit())) {
+                TINT_ICE(Writer, diagnostics)
+                    << "arrays with explicit strides should not exist past the SPIR-V reader";
+                return SizeAndAlign{};
+            }
+            if (arr->Count()->Is<type::RuntimeArrayCount>()) {
+                return SizeAndAlign{arr->Stride(), arr->Align()};
+            }
+            if (auto count = arr->ConstantCount()) {
+                return SizeAndAlign{arr->Stride() * count.value(), arr->Align()};
+            }
+            diagnostics.add_error(diag::System::Writer, type::Array::kErrExpectedConstantCount);
+            return SizeAndAlign{};
+        },
+
+        [&](const type::Struct* str) {
+            // TODO(crbug.com/tint/650): There's an assumption here that MSL's
+            // default structure size and alignment matches WGSL's. We need to
+            // confirm this.
+            return SizeAndAlign{str->Size(), str->Align()};
+        },
+
+        [&](const type::Atomic* atomic) {
+            return MslPackedTypeSizeAndAlign(diagnostics, atomic->Type());
+        },
+
+        [&](Default) {
+            TINT_UNREACHABLE(Writer, diagnostics) << "Unhandled type " << ty->TypeInfo().name;
+            return SizeAndAlign{};
+        });
+}
+
+void PrintF32(utils::StringStream& out, float value) {
+    // Note: Currently inf and nan should not be constructable, but this is implemented for the day
+    // we support them.
+    if (std::isinf(value)) {
+        out << (value >= 0 ? "INFINITY" : "-INFINITY");
+    } else if (std::isnan(value)) {
+        out << "NAN";
+    } else {
+        out << FloatToString(value) << "f";
+    }
+}
+
+void PrintF16(utils::StringStream& out, float value) {
+    // Note: Currently inf and nan should not be constructable, but this is implemented for the day
+    // we support them.
+    if (std::isinf(value)) {
+        // HUGE_VALH evaluates to +infinity.
+        out << (value >= 0 ? "HUGE_VALH" : "-HUGE_VALH");
+    } else if (std::isnan(value)) {
+        // There is no NaN expr for half in MSL, "NAN" is of float type.
+        out << "NAN";
+    } else {
+        out << FloatToString(value) << "h";
+    }
+}
+
+void PrintI32(utils::StringStream& out, int32_t value) {
+    // MSL (and C++) parse `-2147483648` as a `long` because it parses unary minus and `2147483648`
+    // as separate tokens, and the latter doesn't fit into an (32-bit) `int`.
+    // WGSL, on the other hand, parses this as an `i32`.
+    // To avoid issues with `long` to `int` casts, emit `(-2147483647 - 1)` instead, which ensures
+    // the expression type is `int`.
+    if (auto int_min = std::numeric_limits<int32_t>::min(); value == int_min) {
+        out << "(" << int_min + 1 << " - 1)";
+    } else {
+        out << value;
+    }
+}
+
+}  // namespace tint::writer::msl
diff --git a/src/tint/writer/msl/generator_support.h b/src/tint/writer/msl/generator_support.h
new file mode 100644
index 0000000..c510f56
--- /dev/null
+++ b/src/tint/writer/msl/generator_support.h
@@ -0,0 +1,70 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_WRITER_MSL_GENERATOR_SUPPORT_H_
+#define SRC_TINT_WRITER_MSL_GENERATOR_SUPPORT_H_
+
+#include <cstdint>
+#include <string>
+
+#include "src/tint/builtin/builtin_value.h"
+#include "src/tint/builtin/interpolation.h"
+#include "src/tint/diagnostic/diagnostic.h"
+#include "src/tint/type/type.h"
+
+namespace tint::writer::msl {
+
+/// A pair of byte size and alignment `uint32_t`s.
+struct SizeAndAlign {
+    /// The size
+    uint32_t size;
+    /// The alignment
+    uint32_t align;
+};
+
+/// @param diagnostics the diagnostics list
+/// @param ty the type to generate size and align for
+/// @returns the MSL packed type size and alignment in bytes for the given type.
+SizeAndAlign MslPackedTypeSizeAndAlign(diag::List diagnostics, const type::Type* ty);
+
+/// Converts a builtin to an attribute name
+/// @param builtin the builtin to convert
+/// @returns the string name of the builtin or blank on error
+std::string BuiltinToAttribute(builtin::BuiltinValue builtin);
+
+/// Converts interpolation attributes to an MSL attribute
+/// @param type the interpolation type
+/// @param sampling the interpolation sampling
+/// @returns the string name of the attribute or blank on error
+std::string InterpolationToAttribute(builtin::InterpolationType type,
+                                     builtin::InterpolationSampling sampling);
+
+/// Prints a float32 to the output stream
+/// @param out the stream to write too
+/// @param value the float32 value
+void PrintF32(utils::StringStream& out, float value);
+
+/// Prints a float16 to the output stream
+/// @param out the stream to write too
+/// @param value the float16 value
+void PrintF16(utils::StringStream& out, float value);
+
+/// Prints an int32 to the output stream
+/// @param out the stream to write too
+/// @param value the int32 value
+void PrintI32(utils::StringStream& out, int32_t value);
+
+}  // namespace tint::writer::msl
+
+#endif  // SRC_TINT_WRITER_MSL_GENERATOR_SUPPORT_H_
diff --git a/src/tint/writer/msl/generator_support_test.cc b/src/tint/writer/msl/generator_support_test.cc
new file mode 100644
index 0000000..24f6f92
--- /dev/null
+++ b/src/tint/writer/msl/generator_support_test.cc
@@ -0,0 +1,55 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/writer/msl/generator_support.h"
+#include "src/tint/writer/msl/test_helper.h"
+
+namespace tint::writer::msl {
+namespace {
+
+struct MslBuiltinData {
+    builtin::BuiltinValue builtin;
+    const char* attribute_name;
+};
+inline std::ostream& operator<<(std::ostream& out, MslBuiltinData data) {
+    utils::StringStream str;
+    str << data.builtin;
+    out << str.str();
+    return out;
+}
+using MslBuiltinConversionTest = TestParamHelper<MslBuiltinData>;
+TEST_P(MslBuiltinConversionTest, Emit) {
+    auto params = GetParam();
+    EXPECT_EQ(BuiltinToAttribute(params.builtin), std::string(params.attribute_name));
+}
+INSTANTIATE_TEST_SUITE_P(
+    MslGeneratorImplTest,
+    MslBuiltinConversionTest,
+    testing::Values(
+        MslBuiltinData{builtin::BuiltinValue::kPosition, "position"},
+        MslBuiltinData{builtin::BuiltinValue::kVertexIndex, "vertex_id"},
+        MslBuiltinData{builtin::BuiltinValue::kInstanceIndex, "instance_id"},
+        MslBuiltinData{builtin::BuiltinValue::kFrontFacing, "front_facing"},
+        MslBuiltinData{builtin::BuiltinValue::kFragDepth, "depth(any)"},
+        MslBuiltinData{builtin::BuiltinValue::kLocalInvocationId, "thread_position_in_threadgroup"},
+        MslBuiltinData{builtin::BuiltinValue::kLocalInvocationIndex, "thread_index_in_threadgroup"},
+        MslBuiltinData{builtin::BuiltinValue::kGlobalInvocationId, "thread_position_in_grid"},
+        MslBuiltinData{builtin::BuiltinValue::kWorkgroupId, "threadgroup_position_in_grid"},
+        MslBuiltinData{builtin::BuiltinValue::kNumWorkgroups, "threadgroups_per_grid"},
+        MslBuiltinData{builtin::BuiltinValue::kSampleIndex, "sample_id"},
+        MslBuiltinData{builtin::BuiltinValue::kSampleMask, "sample_mask"},
+        MslBuiltinData{builtin::BuiltinValue::kPointSize, "point_size"}));
+
+}  // namespace
+}  // namespace tint::writer::msl
diff --git a/src/tint/writer/msl/ir/generator_impl_ir.cc b/src/tint/writer/msl/ir/generator_impl_ir.cc
new file mode 100644
index 0000000..3209562
--- /dev/null
+++ b/src/tint/writer/msl/ir/generator_impl_ir.cc
@@ -0,0 +1,444 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/writer/msl/ir/generator_impl_ir.h"
+
+#include "src/tint/ir/constant.h"
+#include "src/tint/ir/validate.h"
+#include "src/tint/switch.h"
+#include "src/tint/transform/manager.h"
+#include "src/tint/type/array.h"
+#include "src/tint/type/atomic.h"
+#include "src/tint/type/bool.h"
+#include "src/tint/type/depth_multisampled_texture.h"
+#include "src/tint/type/depth_texture.h"
+#include "src/tint/type/external_texture.h"
+#include "src/tint/type/f16.h"
+#include "src/tint/type/f32.h"
+#include "src/tint/type/i32.h"
+#include "src/tint/type/matrix.h"
+#include "src/tint/type/multisampled_texture.h"
+#include "src/tint/type/pointer.h"
+#include "src/tint/type/sampled_texture.h"
+#include "src/tint/type/storage_texture.h"
+#include "src/tint/type/texture.h"
+#include "src/tint/type/u32.h"
+#include "src/tint/type/vector.h"
+#include "src/tint/type/void.h"
+#include "src/tint/utils/scoped_assignment.h"
+#include "src/tint/writer/msl/generator_support.h"
+
+namespace tint::writer::msl {
+namespace {
+
+void Sanitize(ir::Module* module) {
+    transform::Manager manager;
+    transform::DataMap data;
+
+    transform::DataMap outputs;
+    manager.Run(module, data, outputs);
+}
+
+}  // namespace
+
+// Helper for calling TINT_UNIMPLEMENTED() from a Switch(object_ptr) default case.
+#define UNHANDLED_CASE(object_ptr)           \
+    TINT_UNIMPLEMENTED(Writer, diagnostics_) \
+        << "unhandled case in Switch(): " << (object_ptr ? object_ptr->TypeInfo().name : "<null>")
+
+GeneratorImplIr::GeneratorImplIr(ir::Module* module) : IRTextGenerator(module) {}
+
+GeneratorImplIr::~GeneratorImplIr() = default;
+
+bool GeneratorImplIr::Generate() {
+    auto valid = ir::Validate(*ir_);
+    if (!valid) {
+        diagnostics_ = valid.Failure();
+        return false;
+    }
+
+    // Run the IR transformations to prepare for MSL emission.
+    Sanitize(ir_);
+
+    {
+        TINT_SCOPED_ASSIGNMENT(current_buffer_, &preamble_buffer_);
+        Line() << "#include <metal_stdlib>";
+        Line();
+        Line() << "using namespace metal;";
+    }
+
+    // Emit module-scope declarations.
+    if (ir_->root_block) {
+        // EmitRootBlock(ir_->root_block);
+    }
+
+    // Emit functions.
+    for (auto* func : ir_->functions) {
+        EmitFunction(func);
+    }
+
+    if (diagnostics_.contains_errors()) {
+        return false;
+    }
+
+    return true;
+}
+
+void GeneratorImplIr::EmitFunction(ir::Function* func) {
+    {
+        auto out = Line();
+        EmitType(out, func->ReturnType());
+        out << " " << ir_->NameOf(func).Name() << "() {";
+    }
+    Line() << "}";
+}
+
+const std::string& GeneratorImplIr::ArrayTemplateName() {
+    if (!array_template_name_.empty()) {
+        return array_template_name_;
+    }
+
+    array_template_name_ = UniqueIdentifier("tint_array");
+
+    TINT_SCOPED_ASSIGNMENT(current_buffer_, &preamble_buffer_);
+    Line() << "template<typename T, size_t N>";
+    Line() << "struct " << array_template_name_ << " {";
+
+    {
+        ScopedIndent si(current_buffer_);
+        Line() << "const constant T& operator[](size_t i) const constant { return elements[i]; }";
+        for (auto* space : {"device", "thread", "threadgroup"}) {
+            Line() << space << " T& operator[](size_t i) " << space << " { return elements[i]; }";
+            Line() << "const " << space << " T& operator[](size_t i) const " << space
+                   << " { return elements[i]; }";
+        }
+        Line() << "T elements[N];";
+    }
+    Line() << "};";
+    Line();
+
+    return array_template_name_;
+}
+
+void GeneratorImplIr::EmitAddressSpace(utils::StringStream& out, builtin::AddressSpace sc) {
+    switch (sc) {
+        case builtin::AddressSpace::kFunction:
+        case builtin::AddressSpace::kPrivate:
+        case builtin::AddressSpace::kHandle:
+            out << "thread";
+            break;
+        case builtin::AddressSpace::kWorkgroup:
+            out << "threadgroup";
+            break;
+        case builtin::AddressSpace::kStorage:
+            out << "device";
+            break;
+        case builtin::AddressSpace::kUniform:
+            out << "constant";
+            break;
+        default:
+            TINT_ICE(Writer, diagnostics_) << "unhandled address space: " << sc;
+            break;
+    }
+}
+
+void GeneratorImplIr::EmitType(utils::StringStream& out, const type::Type* ty) {
+    tint::Switch(
+        ty,                                         //
+        [&](const type::Bool*) { out << "bool"; },  //
+        [&](const type::Void*) { out << "void"; },  //
+        [&](const type::F32*) { out << "float"; },  //
+        [&](const type::F16*) { out << "half"; },   //
+        [&](const type::I32*) { out << "int"; },    //
+        [&](const type::U32*) { out << "uint"; },   //
+        [&](const type::Array* arr) {
+            out << ArrayTemplateName() << "<";
+            EmitType(out, arr->ElemType());
+            out << ", ";
+            if (arr->Count()->Is<type::RuntimeArrayCount>()) {
+                out << "1";
+            } else {
+                auto count = arr->ConstantCount();
+                if (!count) {
+                    diagnostics_.add_error(diag::System::Writer,
+                                           type::Array::kErrExpectedConstantCount);
+                    return;
+                }
+                out << count.value();
+            }
+            out << ">";
+        },
+        [&](const type::Vector* vec) {
+            if (vec->Packed()) {
+                out << "packed_";
+            }
+            EmitType(out, vec->type());
+            out << vec->Width();
+        },
+        [&](const type::Matrix* mat) {
+            EmitType(out, mat->type());
+            out << mat->columns() << "x" << mat->rows();
+        },
+        [&](const type::Atomic* atomic) {
+            if (atomic->Type()->Is<type::I32>()) {
+                out << "atomic_int";
+                return;
+            }
+            if (TINT_LIKELY(atomic->Type()->Is<type::U32>())) {
+                out << "atomic_uint";
+                return;
+            }
+            TINT_ICE(Writer, diagnostics_)
+                << "unhandled atomic type " << atomic->Type()->FriendlyName();
+        },
+        [&](const type::Pointer* ptr) {
+            if (ptr->Access() == builtin::Access::kRead) {
+                out << "const ";
+            }
+            EmitAddressSpace(out, ptr->AddressSpace());
+            out << " ";
+            EmitType(out, ptr->StoreType());
+            out << "*";
+        },
+        [&](const type::Sampler*) { out << "sampler"; },  //
+        [&](const type::Texture* tex) {
+            if (TINT_UNLIKELY(tex->Is<type::ExternalTexture>())) {
+                TINT_ICE(Writer, diagnostics_)
+                    << "Multiplanar external texture transform was not run.";
+                return;
+            }
+
+            if (tex->IsAnyOf<type::DepthTexture, type::DepthMultisampledTexture>()) {
+                out << "depth";
+            } else {
+                out << "texture";
+            }
+
+            switch (tex->dim()) {
+                case type::TextureDimension::k1d:
+                    out << "1d";
+                    break;
+                case type::TextureDimension::k2d:
+                    out << "2d";
+                    break;
+                case type::TextureDimension::k2dArray:
+                    out << "2d_array";
+                    break;
+                case type::TextureDimension::k3d:
+                    out << "3d";
+                    break;
+                case type::TextureDimension::kCube:
+                    out << "cube";
+                    break;
+                case type::TextureDimension::kCubeArray:
+                    out << "cube_array";
+                    break;
+                default:
+                    diagnostics_.add_error(diag::System::Writer, "Invalid texture dimensions");
+                    return;
+            }
+            if (tex->IsAnyOf<type::MultisampledTexture, type::DepthMultisampledTexture>()) {
+                out << "_ms";
+            }
+            out << "<";
+            TINT_DEFER(out << ">");
+
+            tint::Switch(
+                tex,  //
+                [&](const type::DepthTexture*) { out << "float, access::sample"; },
+                [&](const type::DepthMultisampledTexture*) { out << "float, access::read"; },
+                [&](const type::StorageTexture* storage) {
+                    EmitType(out, storage->type());
+                    out << ", ";
+
+                    std::string access_str;
+                    if (storage->access() == builtin::Access::kRead) {
+                        out << "access::read";
+                    } else if (storage->access() == builtin::Access::kWrite) {
+                        out << "access::write";
+                    } else {
+                        diagnostics_.add_error(diag::System::Writer,
+                                               "Invalid access control for storage texture");
+                        return;
+                    }
+                },
+                [&](const type::MultisampledTexture* ms) {
+                    EmitType(out, ms->type());
+                    out << ", access::read";
+                },
+                [&](const type::SampledTexture* sampled) {
+                    EmitType(out, sampled->type());
+                    out << ", access::sample";
+                },
+                [&](Default) {
+                    diagnostics_.add_error(diag::System::Writer, "invalid texture type");
+                });
+        },
+        [&](const type::Struct* str) {
+            out << StructName(str);
+
+            TINT_SCOPED_ASSIGNMENT(current_buffer_, &preamble_buffer_);
+            EmitStructType(str);
+        },
+        [&](Default) { UNHANDLED_CASE(ty); });
+}
+
+void GeneratorImplIr::EmitStructType(const type::Struct* str) {
+    auto it = emitted_structs_.emplace(str);
+    if (!it.second) {
+        return;
+    }
+
+    // This does not append directly to the preamble because a struct may require other structs, or
+    // the array template, to get emitted before it. So, the struct emits into a temporary text
+    // buffer, then anything it depends on will emit to the preamble first, and then it copies the
+    // text buffer into the preamble.
+    TextBuffer str_buf;
+    Line(&str_buf) << "struct " << StructName(str) << " {";
+
+    bool is_host_shareable = str->IsHostShareable();
+
+    // Emits a `/* 0xnnnn */` byte offset comment for a struct member.
+    auto add_byte_offset_comment = [&](utils::StringStream& out, uint32_t offset) {
+        std::ios_base::fmtflags saved_flag_state(out.flags());
+        out << "/* 0x" << std::hex << std::setfill('0') << std::setw(4) << offset << " */ ";
+        out.flags(saved_flag_state);
+    };
+
+    auto add_padding = [&](uint32_t size, uint32_t msl_offset) {
+        std::string name;
+        do {
+            name = UniqueIdentifier("tint_pad");
+        } while (str->FindMember(ir_->symbols.Get(name)));
+
+        auto out = Line(&str_buf);
+        add_byte_offset_comment(out, msl_offset);
+        out << ArrayTemplateName() << "<int8_t, " << size << "> " << name << ";";
+    };
+
+    str_buf.IncrementIndent();
+
+    uint32_t msl_offset = 0;
+    for (auto* mem : str->Members()) {
+        auto out = Line(&str_buf);
+        auto mem_name = mem->Name().Name();
+        auto ir_offset = mem->Offset();
+
+        if (is_host_shareable) {
+            if (TINT_UNLIKELY(ir_offset < msl_offset)) {
+                // Unimplementable layout
+                TINT_ICE(Writer, diagnostics_) << "Structure member offset (" << ir_offset
+                                               << ") is behind MSL offset (" << msl_offset << ")";
+                return;
+            }
+
+            // Generate padding if required
+            if (auto padding = ir_offset - msl_offset) {
+                add_padding(padding, msl_offset);
+                msl_offset += padding;
+            }
+
+            add_byte_offset_comment(out, msl_offset);
+        }
+
+        auto* ty = mem->Type();
+
+        EmitType(out, ty);
+        out << " " << mem_name;
+
+        // Emit attributes
+        auto& attributes = mem->Attributes();
+
+        if (auto builtin = attributes.builtin) {
+            auto name = BuiltinToAttribute(builtin.value());
+            if (name.empty()) {
+                diagnostics_.add_error(diag::System::Writer, "unknown builtin");
+                return;
+            }
+            out << " [[" << name << "]]";
+        }
+
+        if (auto location = attributes.location) {
+            auto& pipeline_stage_uses = str->PipelineStageUses();
+            if (TINT_UNLIKELY(pipeline_stage_uses.size() != 1)) {
+                TINT_ICE(Writer, diagnostics_) << "invalid entry point IO struct uses";
+                return;
+            }
+
+            if (pipeline_stage_uses.count(type::PipelineStageUsage::kVertexInput)) {
+                out << " [[attribute(" + std::to_string(location.value()) + ")]]";
+            } else if (pipeline_stage_uses.count(type::PipelineStageUsage::kVertexOutput)) {
+                out << " [[user(locn" + std::to_string(location.value()) + ")]]";
+            } else if (pipeline_stage_uses.count(type::PipelineStageUsage::kFragmentInput)) {
+                out << " [[user(locn" + std::to_string(location.value()) + ")]]";
+            } else if (TINT_LIKELY(
+                           pipeline_stage_uses.count(type::PipelineStageUsage::kFragmentOutput))) {
+                out << " [[color(" + std::to_string(location.value()) + ")]]";
+            } else {
+                TINT_ICE(Writer, diagnostics_) << "invalid use of location decoration";
+                return;
+            }
+        }
+
+        if (auto interpolation = attributes.interpolation) {
+            auto name = InterpolationToAttribute(interpolation->type, interpolation->sampling);
+            if (name.empty()) {
+                diagnostics_.add_error(diag::System::Writer, "unknown interpolation attribute");
+                return;
+            }
+            out << " [[" << name << "]]";
+        }
+
+        if (attributes.invariant) {
+            invariant_define_name_ = UniqueIdentifier("TINT_INVARIANT");
+            out << " " << invariant_define_name_;
+        }
+
+        out << ";";
+
+        if (is_host_shareable) {
+            // Calculate new MSL offset
+            auto size_align = MslPackedTypeSizeAndAlign(diagnostics_, ty);
+            if (TINT_UNLIKELY(msl_offset % size_align.align)) {
+                TINT_ICE(Writer, diagnostics_)
+                    << "Misaligned MSL structure member " << mem_name << " : " << ty->FriendlyName()
+                    << " offset: " << msl_offset << " align: " << size_align.align;
+                return;
+            }
+            msl_offset += size_align.size;
+        }
+    }
+
+    if (is_host_shareable && str->Size() != msl_offset) {
+        add_padding(str->Size() - msl_offset, msl_offset);
+    }
+
+    str_buf.DecrementIndent();
+    Line(&str_buf) << "};";
+
+    preamble_buffer_.Append(str_buf);
+}
+
+void GeneratorImplIr::EmitConstant(utils::StringStream& out, ir::Constant* c) {
+    return tint::Switch(
+        c->Type(),  //
+        [&](const type::Bool*) { out << (c->Value()->ValueAs<bool>() ? "true" : "false"); },
+        [&](const type::I32*) { PrintI32(out, c->Value()->ValueAs<i32>()); },
+        [&](const type::U32*) { out << c->Value()->ValueAs<u32>() << "u"; },
+        [&](const type::F32*) { PrintF32(out, c->Value()->ValueAs<f32>()); },
+        [&](const type::F16*) { PrintF16(out, c->Value()->ValueAs<f16>()); },
+        [&](Default) { UNHANDLED_CASE(c); });
+}
+
+}  // namespace tint::writer::msl
diff --git a/src/tint/writer/msl/ir/generator_impl_ir.h b/src/tint/writer/msl/ir/generator_impl_ir.h
new file mode 100644
index 0000000..89ec1a1
--- /dev/null
+++ b/src/tint/writer/msl/ir/generator_impl_ir.h
@@ -0,0 +1,80 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_WRITER_MSL_IR_GENERATOR_IMPL_IR_H_
+#define SRC_TINT_WRITER_MSL_IR_GENERATOR_IMPL_IR_H_
+
+#include <string>
+#include <unordered_set>
+
+#include "src/tint/diagnostic/diagnostic.h"
+#include "src/tint/ir/module.h"
+#include "src/tint/utils/string_stream.h"
+#include "src/tint/writer/ir_text_generator.h"
+
+namespace tint::writer::msl {
+
+/// Implementation class for the MSL generator
+class GeneratorImplIr : public IRTextGenerator {
+  public:
+    /// Constructor
+    /// @param module the Tint IR module to generate
+    explicit GeneratorImplIr(ir::Module* module);
+    ~GeneratorImplIr() override;
+
+    /// @returns true on successful generation; false otherwise
+    bool Generate();
+
+    /// Emit the function
+    /// @param func the function to emit
+    void EmitFunction(ir::Function* func);
+
+    /// Emit a type
+    /// @param out the stream to emit too
+    /// @param ty the type to emit
+    void EmitType(utils::StringStream& out, const type::Type* ty);
+
+    /// Handles generating a struct declaration. If the structure has already been emitted, then
+    /// this function will simply return without emitting anything.
+    /// @param str the struct to generate
+    void EmitStructType(const type::Struct* str);
+
+    /// Handles generating a address space
+    /// @param out the output of the type stream
+    /// @param sc the address space to generate
+    void EmitAddressSpace(utils::StringStream& out, builtin::AddressSpace sc);
+
+    /// Handles ir::Constant values
+    /// @param out the stream to write the constant too
+    /// @param c the constant to emit
+    void EmitConstant(utils::StringStream& out, ir::Constant* c);
+
+    /// @returns the name of the templated `tint_array` helper type, generating it if needed
+    const std::string& ArrayTemplateName();
+
+    /// Unique name of the tint_array<T, N> template.
+    /// Non-empty only if the template has been generated.
+    std::string array_template_name_;
+
+  private:
+    /// Unique name of the 'TINT_INVARIANT' preprocessor define.
+    /// Non-empty only if an invariant attribute has been generated.
+    std::string invariant_define_name_;
+
+    std::unordered_set<const type::Struct*> emitted_structs_;
+};
+
+}  // namespace tint::writer::msl
+
+#endif  // SRC_TINT_WRITER_MSL_IR_GENERATOR_IMPL_IR_H_
diff --git a/src/tint/writer/msl/ir/generator_impl_ir_constant_test.cc b/src/tint/writer/msl/ir/generator_impl_ir_constant_test.cc
new file mode 100644
index 0000000..41a6139
--- /dev/null
+++ b/src/tint/writer/msl/ir/generator_impl_ir_constant_test.cc
@@ -0,0 +1,66 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/utils/string.h"
+#include "src/tint/writer/msl/ir/test_helper_ir.h"
+
+namespace tint::writer::msl {
+namespace {
+
+using namespace tint::number_suffixes;  // NOLINT
+
+TEST_F(MslGeneratorImplIrTest, Constant_Bool_True) {
+    auto* c = b.Constant(true);
+    generator_.EmitConstant(generator_.Line(), c);
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), std::string("true"));
+}
+
+TEST_F(MslGeneratorImplIrTest, Constant_Bool_False) {
+    auto* c = b.Constant(false);
+    generator_.EmitConstant(generator_.Line(), c);
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), std::string("false"));
+}
+
+TEST_F(MslGeneratorImplIrTest, Constant_i32) {
+    auto* c = b.Constant(-12345_i);
+    generator_.EmitConstant(generator_.Line(), c);
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), std::string("-12345"));
+}
+
+TEST_F(MslGeneratorImplIrTest, Constant_u32) {
+    auto* c = b.Constant(12345_u);
+    generator_.EmitConstant(generator_.Line(), c);
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), std::string("12345u"));
+}
+
+TEST_F(MslGeneratorImplIrTest, Constant_F32) {
+    auto* c = b.Constant(f32((1 << 30) - 4));
+    generator_.EmitConstant(generator_.Line(), c);
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), std::string("1073741824.0f"));
+}
+
+TEST_F(MslGeneratorImplIrTest, Constant_F16) {
+    auto* c = b.Constant(f16((1 << 15) - 8));
+    generator_.EmitConstant(generator_.Line(), c);
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), std::string("32752.0h"));
+}
+
+}  // namespace
+}  // namespace tint::writer::msl
diff --git a/src/tint/writer/msl/ir/generator_impl_ir_function_test.cc b/src/tint/writer/msl/ir/generator_impl_ir_function_test.cc
new file mode 100644
index 0000000..15478b7
--- /dev/null
+++ b/src/tint/writer/msl/ir/generator_impl_ir_function_test.cc
@@ -0,0 +1,35 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/writer/msl/ir/test_helper_ir.h"
+
+namespace tint::writer::msl {
+namespace {
+
+TEST_F(MslGeneratorImplIrTest, Function_Empty) {
+    auto* func = b.Function("foo", ty.void_());
+    func->Block()->Append(b.Return(func));
+
+    ASSERT_TRUE(IRIsValid()) << Error();
+    generator_.EmitFunction(func);
+
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(generator_.Result(), R"(
+void foo() {
+}
+)");
+}
+
+}  // namespace
+}  // namespace tint::writer::msl
diff --git a/src/tint/writer/msl/ir/generator_impl_ir_type_test.cc b/src/tint/writer/msl/ir/generator_impl_ir_type_test.cc
new file mode 100644
index 0000000..3e82c1b
--- /dev/null
+++ b/src/tint/writer/msl/ir/generator_impl_ir_type_test.cc
@@ -0,0 +1,929 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "gmock/gmock.h"
+
+#include "src/tint/type/array.h"
+#include "src/tint/type/depth_multisampled_texture.h"
+#include "src/tint/type/depth_texture.h"
+#include "src/tint/type/matrix.h"
+#include "src/tint/type/multisampled_texture.h"
+#include "src/tint/type/sampled_texture.h"
+#include "src/tint/type/storage_texture.h"
+#include "src/tint/type/struct.h"
+#include "src/tint/utils/string.h"
+#include "src/tint/writer/msl/ir/test_helper_ir.h"
+
+namespace tint::writer::msl {
+namespace {
+
+using namespace tint::builtin::fluent_types;  // NOLINT
+using namespace tint::number_suffixes;        // NOLINT
+
+TEST_F(MslGeneratorImplIrTest, EmitType_Array) {
+    generator_.EmitType(generator_.Line(), ty.array<bool, 4>());
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), R"(template<typename T, size_t N>
+struct tint_array {
+  const constant T& operator[](size_t i) const constant { return elements[i]; }
+  device T& operator[](size_t i) device { return elements[i]; }
+  const device T& operator[](size_t i) const device { return elements[i]; }
+  thread T& operator[](size_t i) thread { return elements[i]; }
+  const thread T& operator[](size_t i) const thread { return elements[i]; }
+  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+  T elements[N];
+};
+
+
+tint_array<bool, 4>)");
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_ArrayOfArray) {
+    generator_.EmitType(generator_.Line(), ty.array(ty.array<bool, 4>(), 5));
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), R"(template<typename T, size_t N>
+struct tint_array {
+  const constant T& operator[](size_t i) const constant { return elements[i]; }
+  device T& operator[](size_t i) device { return elements[i]; }
+  const device T& operator[](size_t i) const device { return elements[i]; }
+  thread T& operator[](size_t i) thread { return elements[i]; }
+  const thread T& operator[](size_t i) const thread { return elements[i]; }
+  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+  T elements[N];
+};
+
+
+tint_array<tint_array<bool, 4>, 5>)");
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_ArrayOfArrayOfArray) {
+    generator_.EmitType(generator_.Line(), ty.array(ty.array(ty.array<bool, 4>(), 5), 6));
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), R"(template<typename T, size_t N>
+struct tint_array {
+  const constant T& operator[](size_t i) const constant { return elements[i]; }
+  device T& operator[](size_t i) device { return elements[i]; }
+  const device T& operator[](size_t i) const device { return elements[i]; }
+  thread T& operator[](size_t i) thread { return elements[i]; }
+  const thread T& operator[](size_t i) const thread { return elements[i]; }
+  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+  T elements[N];
+};
+
+
+tint_array<tint_array<tint_array<bool, 4>, 5>, 6>)");
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_RuntimeArray) {
+    generator_.EmitType(generator_.Line(), ty.array<bool, 0>());
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), R"(template<typename T, size_t N>
+struct tint_array {
+  const constant T& operator[](size_t i) const constant { return elements[i]; }
+  device T& operator[](size_t i) device { return elements[i]; }
+  const device T& operator[](size_t i) const device { return elements[i]; }
+  thread T& operator[](size_t i) thread { return elements[i]; }
+  const thread T& operator[](size_t i) const thread { return elements[i]; }
+  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+  T elements[N];
+};
+
+
+tint_array<bool, 1>)");
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_Bool) {
+    generator_.EmitType(generator_.Line(), ty.bool_());
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), "bool");
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_F32) {
+    generator_.EmitType(generator_.Line(), ty.f32());
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), "float");
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_F16) {
+    generator_.EmitType(generator_.Line(), ty.f16());
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), "half");
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_I32) {
+    generator_.EmitType(generator_.Line(), ty.i32());
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), "int");
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_Matrix_F32) {
+    generator_.EmitType(generator_.Line(), ty.mat2x3<f32>());
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), "float2x3");
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_Matrix_F16) {
+    generator_.EmitType(generator_.Line(), ty.mat2x3<f16>());
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), "half2x3");
+}
+TEST_F(MslGeneratorImplIrTest, EmitType_U32) {
+    generator_.EmitType(generator_.Line(), ty.u32());
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), "uint");
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_Atomic_U32) {
+    generator_.EmitType(generator_.Line(), ty.atomic<u32>());
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), "atomic_uint");
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_Atomic_I32) {
+    generator_.EmitType(generator_.Line(), ty.atomic<i32>());
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), "atomic_int");
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_Vector) {
+    generator_.EmitType(generator_.Line(), ty.vec3<f32>());
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), "float3");
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_VectorPacked) {
+    generator_.EmitType(generator_.Line(), ty.packed_vec(ty.f32(), 3));
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), "packed_float3");
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_Void) {
+    generator_.EmitType(generator_.Line(), ty.void_());
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), "void");
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_Pointer_Workgroup) {
+    generator_.EmitType(generator_.Line(), ty.ptr<workgroup, f32, read_write>());
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), "threadgroup float*");
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_Pointer_Const) {
+    generator_.EmitType(generator_.Line(), ty.ptr<function, f32, read>());
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), "const thread float*");
+}
+
+struct MslAddressSpaceData {
+    builtin::AddressSpace space;
+    std::string result;
+};
+inline std::ostream& operator<<(std::ostream& out, MslAddressSpaceData data) {
+    utils::StringStream str;
+    str << data.space;
+    out << str.str();
+    return out;
+}
+using MslAddressSpaceTest = MslGeneratorImplIrTestWithParam<MslAddressSpaceData>;
+TEST_P(MslAddressSpaceTest, Emit) {}
+INSTANTIATE_TEST_SUITE_P(
+    MslGeneratorImplIrTest,
+    MslAddressSpaceTest,
+    testing::Values(MslAddressSpaceData{builtin::AddressSpace::kWorkgroup, "threadgroup"},
+                    MslAddressSpaceData{builtin::AddressSpace::kFunction, "thread"},
+                    MslAddressSpaceData{builtin::AddressSpace::kPrivate, "thread"},
+                    MslAddressSpaceData{builtin::AddressSpace::kHandle, "thread"},
+                    MslAddressSpaceData{builtin::AddressSpace::kStorage, "device"},
+                    MslAddressSpaceData{builtin::AddressSpace::kUniform, "constant"}));
+
+TEST_F(MslGeneratorImplIrTest, EmitType_Struct) {
+    auto* s = ty.Struct(mod.symbols.New("S"), {
+                                                  {mod.symbols.Register("a"), ty.i32()},
+                                                  {mod.symbols.Register("b"), ty.f32()},
+                                              });
+    generator_.EmitType(generator_.Line(), s);
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_STREQ(std::string(utils::TrimSpace(generator_.Result())).c_str(), R"(struct S {
+  int a;
+  float b;
+};
+
+S)");
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_Struct_Dedup) {
+    auto* s = ty.Struct(mod.symbols.New("S"), {
+                                                  {mod.symbols.Register("a"), ty.i32()},
+                                                  {mod.symbols.Register("b"), ty.f32()},
+                                              });
+    generator_.EmitType(generator_.Line(), s);
+    generator_.EmitType(generator_.Line(), s);
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_STREQ(std::string(utils::TrimSpace(generator_.Result())).c_str(), R"(struct S {
+  int a;
+  float b;
+};
+
+S
+S)");
+}
+
+void FormatMSLField(utils::StringStream& out,
+                    const char* addr,
+                    const char* type,
+                    size_t array_count,
+                    const char* name) {
+    out << "  /* " << std::string(addr) << " */ ";
+    if (array_count == 0) {
+        out << type << " ";
+    } else {
+        out << "tint_array<" << type << ", " << std::to_string(array_count) << "> ";
+    }
+    out << name << ";\n";
+}
+
+#define CHECK_TYPE_SIZE_AND_ALIGN(TYPE, SIZE, ALIGN)      \
+    static_assert(sizeof(TYPE) == SIZE, "Bad type size"); \
+    static_assert(alignof(TYPE) == ALIGN, "Bad type alignment")
+
+// Declare C++ types that match the size and alignment of the types of the same
+// name in MSL.
+#define DECLARE_TYPE(NAME, SIZE, ALIGN) \
+    struct alignas(ALIGN) NAME {        \
+        uint8_t _[SIZE];                \
+    };                                  \
+    CHECK_TYPE_SIZE_AND_ALIGN(NAME, SIZE, ALIGN)
+
+// Size and alignments taken from the MSL spec:
+// https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf
+DECLARE_TYPE(float2, 8, 8);
+DECLARE_TYPE(float3, 12, 4);
+DECLARE_TYPE(float4, 16, 16);
+DECLARE_TYPE(float2x2, 16, 8);
+DECLARE_TYPE(float2x3, 32, 16);
+DECLARE_TYPE(float2x4, 32, 16);
+DECLARE_TYPE(float3x2, 24, 8);
+DECLARE_TYPE(float3x3, 48, 16);
+DECLARE_TYPE(float3x4, 48, 16);
+DECLARE_TYPE(float4x2, 32, 8);
+DECLARE_TYPE(float4x3, 64, 16);
+DECLARE_TYPE(float4x4, 64, 16);
+DECLARE_TYPE(half2, 4, 4);
+DECLARE_TYPE(packed_half3, 6, 2);
+DECLARE_TYPE(half4, 8, 8);
+DECLARE_TYPE(half2x2, 8, 4);
+DECLARE_TYPE(half2x3, 16, 8);
+DECLARE_TYPE(half2x4, 16, 8);
+DECLARE_TYPE(half3x2, 12, 4);
+DECLARE_TYPE(half3x3, 24, 8);
+DECLARE_TYPE(half3x4, 24, 8);
+DECLARE_TYPE(half4x2, 16, 4);
+DECLARE_TYPE(half4x3, 32, 8);
+DECLARE_TYPE(half4x4, 32, 8);
+using uint = unsigned int;
+
+struct MemberData {
+    Symbol name;
+    const type::Type* type;
+    uint32_t size = 0;
+    uint32_t align = 0;
+};
+type::Struct* MkStruct(ir::Module& mod,
+                       type::Manager& ty,
+                       std::string_view name,
+                       utils::VectorRef<MemberData> data) {
+    utils::Vector<const type::StructMember*, 26> members;
+    uint32_t align = 0;
+    uint32_t size = 0;
+    for (uint32_t i = 0; i < data.Length(); ++i) {
+        auto& d = data[i];
+
+        uint32_t mem_align = d.align == 0 ? d.type->Align() : d.align;
+        uint32_t mem_size = d.size == 0 ? d.type->Size() : d.size;
+
+        uint32_t offset = utils::RoundUp(mem_align, size);
+        members.Push(ty.Get<type::StructMember>(d.name, d.type, i, offset, mem_align, mem_size,
+                                                type::StructMemberAttributes{}));
+
+        align = std::max(align, mem_align);
+        size = offset + mem_size;
+    }
+
+    return ty.Get<type::Struct>(mod.symbols.New(name), std::move(members), align,
+                                utils::RoundUp(align, size), size);
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_Struct_Layout_NonComposites) {
+    utils::Vector<MemberData, 26> data = {{mod.symbols.Register("a"), ty.i32(), 32},        //
+                                          {mod.symbols.Register("b"), ty.f32(), 128, 128},  //
+                                          {mod.symbols.Register("c"), ty.vec2<f32>()},      //
+                                          {mod.symbols.Register("d"), ty.u32()},            //
+                                          {mod.symbols.Register("e"), ty.vec3<f32>()},      //
+                                          {mod.symbols.Register("f"), ty.u32()},            //
+                                          {mod.symbols.Register("g"), ty.vec4<f32>()},      //
+                                          {mod.symbols.Register("h"), ty.u32()},            //
+                                          {mod.symbols.Register("i"), ty.mat2x2<f32>()},    //
+                                          {mod.symbols.Register("j"), ty.u32()},            //
+                                          {mod.symbols.Register("k"), ty.mat2x3<f32>()},    //
+                                          {mod.symbols.Register("l"), ty.u32()},            //
+                                          {mod.symbols.Register("m"), ty.mat2x4<f32>()},    //
+                                          {mod.symbols.Register("n"), ty.u32()},            //
+                                          {mod.symbols.Register("o"), ty.mat3x2<f32>()},    //
+                                          {mod.symbols.Register("p"), ty.u32()},            //
+                                          {mod.symbols.Register("q"), ty.mat3x3<f32>()},    //
+                                          {mod.symbols.Register("r"), ty.u32()},            //
+                                          {mod.symbols.Register("s"), ty.mat3x4<f32>()},    //
+                                          {mod.symbols.Register("t"), ty.u32()},            //
+                                          {mod.symbols.Register("u"), ty.mat4x2<f32>()},    //
+                                          {mod.symbols.Register("v"), ty.u32()},            //
+                                          {mod.symbols.Register("w"), ty.mat4x3<f32>()},    //
+                                          {mod.symbols.Register("x"), ty.u32()},            //
+                                          {mod.symbols.Register("y"), ty.mat4x4<f32>()},    //
+                                          {mod.symbols.Register("z"), ty.f32()}};
+
+    auto* s = MkStruct(mod, ty, "S", data);
+    s->AddUsage(builtin::AddressSpace::kStorage);
+
+    // ALL_FIELDS() calls the macro FIELD(ADDR, TYPE, ARRAY_COUNT, NAME)
+    // for each field of the structure s.
+#define ALL_FIELDS()                       \
+    FIELD(0x0000, int, 0, a)               \
+    FIELD(0x0004, int8_t, 124, tint_pad)   \
+    FIELD(0x0080, float, 0, b)             \
+    FIELD(0x0084, int8_t, 124, tint_pad_1) \
+    FIELD(0x0100, float2, 0, c)            \
+    FIELD(0x0108, uint, 0, d)              \
+    FIELD(0x010c, int8_t, 4, tint_pad_2)   \
+    FIELD(0x0110, float3, 0, e)            \
+    FIELD(0x011c, uint, 0, f)              \
+    FIELD(0x0120, float4, 0, g)            \
+    FIELD(0x0130, uint, 0, h)              \
+    FIELD(0x0134, int8_t, 4, tint_pad_3)   \
+    FIELD(0x0138, float2x2, 0, i)          \
+    FIELD(0x0148, uint, 0, j)              \
+    FIELD(0x014c, int8_t, 4, tint_pad_4)   \
+    FIELD(0x0150, float2x3, 0, k)          \
+    FIELD(0x0170, uint, 0, l)              \
+    FIELD(0x0174, int8_t, 12, tint_pad_5)  \
+    FIELD(0x0180, float2x4, 0, m)          \
+    FIELD(0x01a0, uint, 0, n)              \
+    FIELD(0x01a4, int8_t, 4, tint_pad_6)   \
+    FIELD(0x01a8, float3x2, 0, o)          \
+    FIELD(0x01c0, uint, 0, p)              \
+    FIELD(0x01c4, int8_t, 12, tint_pad_7)  \
+    FIELD(0x01d0, float3x3, 0, q)          \
+    FIELD(0x0200, uint, 0, r)              \
+    FIELD(0x0204, int8_t, 12, tint_pad_8)  \
+    FIELD(0x0210, float3x4, 0, s)          \
+    FIELD(0x0240, uint, 0, t)              \
+    FIELD(0x0244, int8_t, 4, tint_pad_9)   \
+    FIELD(0x0248, float4x2, 0, u)          \
+    FIELD(0x0268, uint, 0, v)              \
+    FIELD(0x026c, int8_t, 4, tint_pad_10)  \
+    FIELD(0x0270, float4x3, 0, w)          \
+    FIELD(0x02b0, uint, 0, x)              \
+    FIELD(0x02b4, int8_t, 12, tint_pad_11) \
+    FIELD(0x02c0, float4x4, 0, y)          \
+    FIELD(0x0300, float, 0, z)             \
+    FIELD(0x0304, int8_t, 124, tint_pad_12)
+
+    // Check that the generated string is as expected.
+    utils::StringStream expect;
+    expect << R"(template<typename T, size_t N>
+struct tint_array {
+  const constant T& operator[](size_t i) const constant { return elements[i]; }
+  device T& operator[](size_t i) device { return elements[i]; }
+  const device T& operator[](size_t i) const device { return elements[i]; }
+  thread T& operator[](size_t i) thread { return elements[i]; }
+  const thread T& operator[](size_t i) const thread { return elements[i]; }
+  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+  T elements[N];
+};
+
+)";
+
+    expect << "struct S {\n";
+#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \
+    FormatMSLField(expect, #ADDR, #TYPE, ARRAY_COUNT, #NAME);
+    ALL_FIELDS()
+#undef FIELD
+    expect << "};\n\nS";
+
+    generator_.EmitType(generator_.Line(), s);
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), expect.str());
+
+    // 1.4 Metal and C++14
+    // The Metal programming language is a C++14-based Specification with
+    // extensions and restrictions. Refer to the C++14 Specification (also
+    // known as the ISO/IEC JTC1/SC22/WG21 N4431 Language Specification) for a
+    // detailed description of the language grammar.
+    //
+    // Tint is written in C++14, so use the compiler to verify the generated
+    // layout is as expected for C++14 / MSL.
+    {
+        struct S {
+#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) std::array<TYPE, ARRAY_COUNT ? ARRAY_COUNT : 1> NAME;
+            ALL_FIELDS()
+#undef FIELD
+        };
+
+#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \
+    EXPECT_EQ(ADDR, static_cast<int>(offsetof(S, NAME))) << "Field " << #NAME;
+        ALL_FIELDS()
+#undef FIELD
+    }
+#undef ALL_FIELDS
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_Struct_Layout_Structures) {
+    // inner_x: size(1024), align(512)
+    utils::Vector<MemberData, 2> inner_x_data = {{{mod.symbols.Register("a"), ty.i32()},  //
+                                                  {mod.symbols.Register("b"), ty.f32(), 0, 512}}};
+    auto* inner_x = MkStruct(mod, ty, "inner_x", inner_x_data);
+
+    // inner_y: size(516), align(4)
+    utils::Vector<MemberData, 2> inner_y_data = {{mod.symbols.Register("a"), ty.i32(), 512},
+                                                 {mod.symbols.Register("b"), ty.f32()}};
+
+    auto* inner_y = MkStruct(mod, ty, "inner_y", inner_y_data);
+
+    auto* s = ty.Struct(mod.symbols.New("S"), {{mod.symbols.Register("a"), ty.i32()},
+                                               {mod.symbols.Register("b"), inner_x},
+                                               {mod.symbols.Register("c"), ty.f32()},
+                                               {mod.symbols.Register("d"), inner_y},
+                                               {mod.symbols.Register("e"), ty.f32()}});
+    const_cast<type::Struct*>(s)->AddUsage(builtin::AddressSpace::kStorage);
+
+// ALL_FIELDS() calls the macro FIELD(ADDR, TYPE, ARRAY_COUNT, NAME)
+// for each field of the structure s.
+#define ALL_FIELDS()                     \
+    FIELD(0x0000, int, 0, a)             \
+    FIELD(0x0004, int8_t, 508, tint_pad) \
+    FIELD(0x0200, inner_x, 0, b)         \
+    FIELD(0x0600, float, 0, c)           \
+    FIELD(0x0604, inner_y, 0, d)         \
+    FIELD(0x0808, float, 0, e)           \
+    FIELD(0x080c, int8_t, 500, tint_pad_1)
+
+    // Check that the generated string is as expected.
+    utils::StringStream expect;
+    expect << R"(template<typename T, size_t N>
+struct tint_array {
+  const constant T& operator[](size_t i) const constant { return elements[i]; }
+  device T& operator[](size_t i) device { return elements[i]; }
+  const device T& operator[](size_t i) const device { return elements[i]; }
+  thread T& operator[](size_t i) thread { return elements[i]; }
+  const thread T& operator[](size_t i) const thread { return elements[i]; }
+  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+  T elements[N];
+};
+
+struct inner_x {
+  int a;
+  float b;
+};
+struct inner_y {
+  int a;
+  float b;
+};
+)";
+
+    expect << "struct S {\n";
+#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \
+    FormatMSLField(expect, #ADDR, #TYPE, ARRAY_COUNT, #NAME);
+    ALL_FIELDS()
+#undef FIELD
+    expect << "};\n\nS";
+
+    generator_.EmitType(generator_.Line(), s);
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), expect.str());
+
+    // 1.4 Metal and C++14
+    // The Metal programming language is a C++14-based Specification with
+    // extensions and restrictions. Refer to the C++14 Specification (also
+    // known as the ISO/IEC JTC1/SC22/WG21 N4431 Language Specification) for a
+    // detailed description of the language grammar.
+    //
+    // Tint is written in C++14, so use the compiler to verify the generated
+    // layout is as expected for C++14 / MSL.
+    {
+        struct inner_x {
+            uint32_t a;
+            alignas(512) float b;
+        };
+        CHECK_TYPE_SIZE_AND_ALIGN(inner_x, 1024, 512);
+
+        struct inner_y {
+            uint32_t a[128];
+            float b;
+        };
+        CHECK_TYPE_SIZE_AND_ALIGN(inner_y, 516, 4);
+
+        struct S {
+#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) std::array<TYPE, ARRAY_COUNT ? ARRAY_COUNT : 1> NAME;
+            ALL_FIELDS()
+#undef FIELD
+        };
+
+#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \
+    EXPECT_EQ(ADDR, static_cast<int>(offsetof(S, NAME))) << "Field " << #NAME;
+        ALL_FIELDS()
+#undef FIELD
+    }
+
+#undef ALL_FIELDS
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_Struct_Layout_ArrayDefaultStride) {
+    // inner: size(1024), align(512)
+    utils::Vector<MemberData, 2> inner_data = {{mod.symbols.Register("a"), ty.i32()},
+                                               {mod.symbols.Register("b"), ty.f32(), 0, 512}};
+
+    auto* inner = MkStruct(mod, ty, "inner", inner_data);
+
+    // array_x: size(28), align(4)
+    auto array_x = ty.array<f32, 7>();
+
+    // array_y: size(4096), align(512)
+    auto array_y = ty.array(inner, 4_u);
+
+    // array_z: size(4), align(4)
+    auto array_z = ty.array<f32>();
+
+    auto* s = ty.Struct(mod.symbols.New("S"), {{mod.symbols.Register("a"), ty.i32()},
+                                               {mod.symbols.Register("b"), array_x},
+                                               {mod.symbols.Register("c"), ty.f32()},
+                                               {mod.symbols.Register("d"), array_y},
+                                               {mod.symbols.Register("e"), ty.f32()},
+                                               {mod.symbols.Register("f"), array_z}});
+    const_cast<type::Struct*>(s)->AddUsage(builtin::AddressSpace::kStorage);
+
+    // ALL_FIELDS() calls the macro FIELD(ADDR, TYPE, ARRAY_COUNT, NAME)
+    // for each field of the structure s.
+#define ALL_FIELDS()                     \
+    FIELD(0x0000, int, 0, a)             \
+    FIELD(0x0004, float, 7, b)           \
+    FIELD(0x0020, float, 0, c)           \
+    FIELD(0x0024, int8_t, 476, tint_pad) \
+    FIELD(0x0200, inner, 4, d)           \
+    FIELD(0x1200, float, 0, e)           \
+    FIELD(0x1204, float, 1, f)           \
+    FIELD(0x1208, int8_t, 504, tint_pad_1)
+
+    // Check that the generated string is as expected.
+    utils::StringStream expect;
+
+    expect << R"(template<typename T, size_t N>
+struct tint_array {
+  const constant T& operator[](size_t i) const constant { return elements[i]; }
+  device T& operator[](size_t i) device { return elements[i]; }
+  const device T& operator[](size_t i) const device { return elements[i]; }
+  thread T& operator[](size_t i) thread { return elements[i]; }
+  const thread T& operator[](size_t i) const thread { return elements[i]; }
+  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+  T elements[N];
+};
+
+struct inner {
+  int a;
+  float b;
+};
+)";
+
+    expect << "struct S {\n";
+#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \
+    FormatMSLField(expect, #ADDR, #TYPE, ARRAY_COUNT, #NAME);
+    ALL_FIELDS()
+#undef FIELD
+    expect << "};\n\nS";
+
+    generator_.EmitType(generator_.Line(), s);
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), expect.str());
+
+    // 1.4 Metal and C++14
+    // The Metal programming language is a C++14-based Specification with
+    // extensions and restrictions. Refer to the C++14 Specification (also
+    // known as the ISO/IEC JTC1/SC22/WG21 N4431 Language Specification) for a
+    // detailed description of the language grammar.
+    //
+    // Tint is written in C++14, so use the compiler to verify the generated
+    // layout is as expected for C++14 / MSL.
+    {
+        struct inner {
+            uint32_t a;
+            alignas(512) float b;
+        };
+        CHECK_TYPE_SIZE_AND_ALIGN(inner, 1024, 512);
+
+        // array_x: size(28), align(4)
+        using array_x = std::array<float, 7>;
+        CHECK_TYPE_SIZE_AND_ALIGN(array_x, 28, 4);
+
+        // array_y: size(4096), align(512)
+        using array_y = std::array<inner, 4>;
+        CHECK_TYPE_SIZE_AND_ALIGN(array_y, 4096, 512);
+
+        // array_z: size(4), align(4)
+        using array_z = std::array<float, 1>;
+        CHECK_TYPE_SIZE_AND_ALIGN(array_z, 4, 4);
+
+        struct S {
+#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) std::array<TYPE, ARRAY_COUNT ? ARRAY_COUNT : 1> NAME;
+            ALL_FIELDS()
+#undef FIELD
+        };
+
+#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \
+    EXPECT_EQ(ADDR, static_cast<int>(offsetof(S, NAME))) << "Field " << #NAME;
+        ALL_FIELDS()
+#undef FIELD
+    }
+
+#undef ALL_FIELDS
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_Struct_Layout_ArrayVec3DefaultStride) {
+    // array: size(64), align(16)
+    auto array = ty.array<vec3<f32>, 4>();
+
+    auto* s = ty.Struct(mod.symbols.New("S"), {
+                                                  {mod.symbols.Register("a"), ty.i32()},
+                                                  {mod.symbols.Register("b"), array},
+                                                  {mod.symbols.Register("c"), ty.i32()},
+                                              });
+    const_cast<type::Struct*>(s)->AddUsage(builtin::AddressSpace::kStorage);
+
+    // ALL_FIELDS() calls the macro FIELD(ADDR, TYPE, ARRAY_COUNT, NAME)
+    // for each field of the structure s.
+#define ALL_FIELDS()                    \
+    FIELD(0x0000, int, 0, a)            \
+    FIELD(0x0004, int8_t, 12, tint_pad) \
+    FIELD(0x0010, float3, 4, b)         \
+    FIELD(0x0050, int, 0, c)            \
+    FIELD(0x0054, int8_t, 12, tint_pad_1)
+
+    // Check that the generated string is as expected.
+    utils::StringStream expect;
+
+    expect << R"(template<typename T, size_t N>
+struct tint_array {
+  const constant T& operator[](size_t i) const constant { return elements[i]; }
+  device T& operator[](size_t i) device { return elements[i]; }
+  const device T& operator[](size_t i) const device { return elements[i]; }
+  thread T& operator[](size_t i) thread { return elements[i]; }
+  const thread T& operator[](size_t i) const thread { return elements[i]; }
+  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+  T elements[N];
+};
+
+)";
+
+    expect << "struct S {\n";
+#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \
+    FormatMSLField(expect, #ADDR, #TYPE, ARRAY_COUNT, #NAME);
+    ALL_FIELDS()
+#undef FIELD
+    expect << "};\n\nS";
+
+    generator_.EmitType(generator_.Line(), s);
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), expect.str());
+}
+
+TEST_F(MslGeneratorImplIrTest, AttemptTintPadSymbolCollision) {
+    utils::Vector<MemberData, 26> data = {
+        // uses symbols tint_pad_[0..9] and tint_pad_[20..35]
+        {mod.symbols.Register("tint_pad_2"), ty.i32(), 32},         //
+        {mod.symbols.Register("tint_pad_20"), ty.f32(), 128, 128},  //
+        {mod.symbols.Register("tint_pad_33"), ty.vec2<f32>()},      //
+        {mod.symbols.Register("tint_pad_1"), ty.u32()},             //
+        {mod.symbols.Register("tint_pad_3"), ty.vec3<f32>()},       //
+        {mod.symbols.Register("tint_pad_7"), ty.u32()},             //
+        {mod.symbols.Register("tint_pad_25"), ty.vec4<f32>()},      //
+        {mod.symbols.Register("tint_pad_5"), ty.u32()},             //
+        {mod.symbols.Register("tint_pad_27"), ty.mat2x2<f32>()},    //
+        {mod.symbols.Register("tint_pad_24"), ty.u32()},            //
+        {mod.symbols.Register("tint_pad_23"), ty.mat2x3<f32>()},    //
+        {mod.symbols.Register("tint_pad"), ty.u32()},               //
+        {mod.symbols.Register("tint_pad_8"), ty.mat2x4<f32>()},     //
+        {mod.symbols.Register("tint_pad_26"), ty.u32()},            //
+        {mod.symbols.Register("tint_pad_29"), ty.mat3x2<f32>()},    //
+        {mod.symbols.Register("tint_pad_6"), ty.u32()},             //
+        {mod.symbols.Register("tint_pad_22"), ty.mat3x3<f32>()},    //
+        {mod.symbols.Register("tint_pad_32"), ty.u32()},            //
+        {mod.symbols.Register("tint_pad_34"), ty.mat3x4<f32>()},    //
+        {mod.symbols.Register("tint_pad_35"), ty.u32()},            //
+        {mod.symbols.Register("tint_pad_30"), ty.mat4x2<f32>()},    //
+        {mod.symbols.Register("tint_pad_9"), ty.u32()},             //
+        {mod.symbols.Register("tint_pad_31"), ty.mat4x3<f32>()},    //
+        {mod.symbols.Register("tint_pad_28"), ty.u32()},            //
+        {mod.symbols.Register("tint_pad_4"), ty.mat4x4<f32>()},     //
+        {mod.symbols.Register("tint_pad_21"), ty.f32()}};
+
+    auto* s = MkStruct(mod, ty, "S", data);
+    s->AddUsage(builtin::AddressSpace::kStorage);
+
+    auto expect = R"(template<typename T, size_t N>
+struct tint_array {
+  const constant T& operator[](size_t i) const constant { return elements[i]; }
+  device T& operator[](size_t i) device { return elements[i]; }
+  const device T& operator[](size_t i) const device { return elements[i]; }
+  thread T& operator[](size_t i) thread { return elements[i]; }
+  const thread T& operator[](size_t i) const thread { return elements[i]; }
+  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+  T elements[N];
+};
+
+struct S {
+  /* 0x0000 */ int tint_pad_2;
+  /* 0x0004 */ tint_array<int8_t, 124> tint_pad_10;
+  /* 0x0080 */ float tint_pad_20;
+  /* 0x0084 */ tint_array<int8_t, 124> tint_pad_11;
+  /* 0x0100 */ float2 tint_pad_33;
+  /* 0x0108 */ uint tint_pad_1;
+  /* 0x010c */ tint_array<int8_t, 4> tint_pad_12;
+  /* 0x0110 */ float3 tint_pad_3;
+  /* 0x011c */ uint tint_pad_7;
+  /* 0x0120 */ float4 tint_pad_25;
+  /* 0x0130 */ uint tint_pad_5;
+  /* 0x0134 */ tint_array<int8_t, 4> tint_pad_13;
+  /* 0x0138 */ float2x2 tint_pad_27;
+  /* 0x0148 */ uint tint_pad_24;
+  /* 0x014c */ tint_array<int8_t, 4> tint_pad_14;
+  /* 0x0150 */ float2x3 tint_pad_23;
+  /* 0x0170 */ uint tint_pad;
+  /* 0x0174 */ tint_array<int8_t, 12> tint_pad_15;
+  /* 0x0180 */ float2x4 tint_pad_8;
+  /* 0x01a0 */ uint tint_pad_26;
+  /* 0x01a4 */ tint_array<int8_t, 4> tint_pad_16;
+  /* 0x01a8 */ float3x2 tint_pad_29;
+  /* 0x01c0 */ uint tint_pad_6;
+  /* 0x01c4 */ tint_array<int8_t, 12> tint_pad_17;
+  /* 0x01d0 */ float3x3 tint_pad_22;
+  /* 0x0200 */ uint tint_pad_32;
+  /* 0x0204 */ tint_array<int8_t, 12> tint_pad_18;
+  /* 0x0210 */ float3x4 tint_pad_34;
+  /* 0x0240 */ uint tint_pad_35;
+  /* 0x0244 */ tint_array<int8_t, 4> tint_pad_19;
+  /* 0x0248 */ float4x2 tint_pad_30;
+  /* 0x0268 */ uint tint_pad_9;
+  /* 0x026c */ tint_array<int8_t, 4> tint_pad_36;
+  /* 0x0270 */ float4x3 tint_pad_31;
+  /* 0x02b0 */ uint tint_pad_28;
+  /* 0x02b4 */ tint_array<int8_t, 12> tint_pad_37;
+  /* 0x02c0 */ float4x4 tint_pad_4;
+  /* 0x0300 */ float tint_pad_21;
+  /* 0x0304 */ tint_array<int8_t, 124> tint_pad_38;
+};
+
+S)";
+
+    generator_.EmitType(generator_.Line(), s);
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_STREQ(std::string(utils::TrimSpace(generator_.Result())).c_str(), expect);
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_Sampler) {
+    generator_.EmitType(generator_.Line(), ty.sampler());
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), "sampler");
+}
+
+TEST_F(MslGeneratorImplIrTest, EmitType_SamplerComparison) {
+    generator_.EmitType(generator_.Line(), ty.comparison_sampler());
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), "sampler");
+}
+
+struct MslDepthTextureData {
+    type::TextureDimension dim;
+    std::string result;
+};
+inline std::ostream& operator<<(std::ostream& out, MslDepthTextureData data) {
+    utils::StringStream str;
+    str << data.dim;
+    out << str.str();
+    return out;
+}
+using MslIrDepthTexturesTest = MslGeneratorImplIrTestWithParam<MslDepthTextureData>;
+TEST_P(MslIrDepthTexturesTest, Emit) {
+    auto params = GetParam();
+
+    auto* t = ty.Get<type::DepthTexture>(params.dim);
+    generator_.EmitType(generator_.Line(), t);
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), params.result);
+}
+INSTANTIATE_TEST_SUITE_P(
+    MslGeneratorImplIrTest,
+    MslIrDepthTexturesTest,
+    testing::Values(
+        MslDepthTextureData{type::TextureDimension::k2d, "depth2d<float, access::sample>"},
+        MslDepthTextureData{type::TextureDimension::k2dArray,
+                            "depth2d_array<float, access::sample>"},
+        MslDepthTextureData{type::TextureDimension::kCube, "depthcube<float, access::sample>"},
+        MslDepthTextureData{type::TextureDimension::kCubeArray,
+                            "depthcube_array<float, access::sample>"}));
+
+TEST_F(MslGeneratorImplIrTest, EmiType_DepthMultisampledTexture) {
+    auto* t = ty.Get<type::DepthMultisampledTexture>(type::TextureDimension::k2d);
+    generator_.EmitType(generator_.Line(), t);
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), "depth2d_ms<float, access::read>");
+}
+
+struct MslTextureData {
+    type::TextureDimension dim;
+    std::string result;
+};
+inline std::ostream& operator<<(std::ostream& out, MslTextureData data) {
+    utils::StringStream str;
+    str << data.dim;
+    out << str.str();
+    return out;
+}
+using MslIrSampledtexturesTest = MslGeneratorImplIrTestWithParam<MslTextureData>;
+TEST_P(MslIrSampledtexturesTest, Emit) {
+    auto params = GetParam();
+
+    auto* t = ty.Get<type::SampledTexture>(params.dim, ty.f32());
+    generator_.EmitType(generator_.Line(), t);
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), params.result);
+}
+INSTANTIATE_TEST_SUITE_P(
+    MslGeneratorImplIrTest,
+    MslIrSampledtexturesTest,
+    testing::Values(
+        MslTextureData{type::TextureDimension::k1d, "texture1d<float, access::sample>"},
+        MslTextureData{type::TextureDimension::k2d, "texture2d<float, access::sample>"},
+        MslTextureData{type::TextureDimension::k2dArray, "texture2d_array<float, access::sample>"},
+        MslTextureData{type::TextureDimension::k3d, "texture3d<float, access::sample>"},
+        MslTextureData{type::TextureDimension::kCube, "texturecube<float, access::sample>"},
+        MslTextureData{type::TextureDimension::kCubeArray,
+                       "texturecube_array<float, access::sample>"}));
+
+TEST_F(MslGeneratorImplIrTest, Emit_TypeMultisampledTexture) {
+    auto* ms = ty.Get<type::MultisampledTexture>(type::TextureDimension::k2d, ty.u32());
+    generator_.EmitType(generator_.Line(), ms);
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), "texture2d_ms<uint, access::read>");
+}
+
+struct MslStorageTextureData {
+    type::TextureDimension dim;
+    std::string result;
+};
+inline std::ostream& operator<<(std::ostream& out, MslStorageTextureData data) {
+    utils::StringStream str;
+    str << data.dim;
+    return out << str.str();
+}
+using MslIrStorageTexturesTest = MslGeneratorImplIrTestWithParam<MslStorageTextureData>;
+TEST_P(MslIrStorageTexturesTest, Emit) {
+    auto params = GetParam();
+
+    auto* f32 = const_cast<type::F32*>(ty.f32());
+    auto s = ty.Get<type::StorageTexture>(params.dim, builtin::TexelFormat::kR32Float,
+                                          builtin::Access::kWrite, f32);
+    generator_.EmitType(generator_.Line(), s);
+    ASSERT_TRUE(generator_.Diagnostics().empty()) << generator_.Diagnostics().str();
+    EXPECT_EQ(utils::TrimSpace(generator_.Result()), params.result);
+}
+INSTANTIATE_TEST_SUITE_P(
+    MslGeneratorImplIrTest,
+    MslIrStorageTexturesTest,
+    testing::Values(
+        MslStorageTextureData{type::TextureDimension::k1d, "texture1d<float, access::write>"},
+        MslStorageTextureData{type::TextureDimension::k2d, "texture2d<float, access::write>"},
+        MslStorageTextureData{type::TextureDimension::k2dArray,
+                              "texture2d_array<float, access::write>"},
+        MslStorageTextureData{type::TextureDimension::k3d, "texture3d<float, access::write>"}));
+
+}  // namespace
+}  // namespace tint::writer::msl
diff --git a/src/tint/writer/msl/ir/test_helper_ir.h b/src/tint/writer/msl/ir/test_helper_ir.h
new file mode 100644
index 0000000..38bbf9b
--- /dev/null
+++ b/src/tint/writer/msl/ir/test_helper_ir.h
@@ -0,0 +1,68 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_WRITER_MSL_IR_TEST_HELPER_IR_H_
+#define SRC_TINT_WRITER_MSL_IR_TEST_HELPER_IR_H_
+
+#include <string>
+
+#include "gtest/gtest.h"
+#include "src/tint/ir/builder.h"
+#include "src/tint/ir/validate.h"
+#include "src/tint/writer/msl/ir/generator_impl_ir.h"
+
+namespace tint::writer::msl {
+
+/// Base helper class for testing the MSL generator implementation.
+template <typename BASE>
+class MslGeneratorIrTestHelperBase : public BASE {
+  public:
+    MslGeneratorIrTestHelperBase() : generator_(&mod) {}
+
+    /// The test module.
+    ir::Module mod;
+    /// The test builder.
+    ir::Builder b{mod};
+    /// The type manager.
+    type::Manager& ty{mod.Types()};
+
+  protected:
+    /// The MSL generator.
+    GeneratorImplIr generator_;
+
+    /// Validation errors
+    std::string err_;
+
+    /// @returns the error string from the validation
+    std::string Error() const { return err_; }
+
+    /// @returns true if the IR module is valid
+    bool IRIsValid() {
+        auto res = ir::Validate(mod);
+        if (!res) {
+            err_ = res.Failure().str();
+            return false;
+        }
+        return true;
+    }
+};
+
+using MslGeneratorImplIrTest = MslGeneratorIrTestHelperBase<testing::Test>;
+
+template <typename T>
+using MslGeneratorImplIrTestWithParam = MslGeneratorIrTestHelperBase<testing::TestWithParam<T>>;
+
+}  // namespace tint::writer::msl
+
+#endif  // SRC_TINT_WRITER_MSL_IR_TEST_HELPER_IR_H_
diff --git a/src/tint/writer/spirv/binary_writer.h b/src/tint/writer/spirv/binary_writer.h
index 0b1c234..b9696b8 100644
--- a/src/tint/writer/spirv/binary_writer.h
+++ b/src/tint/writer/spirv/binary_writer.h
@@ -42,10 +42,10 @@
     void WriteInstruction(const Instruction& inst);
 
     /// @returns the assembled SPIR-V
-    const std::vector<uint32_t>& result() const { return out_; }
+    const std::vector<uint32_t>& Result() const { return out_; }
 
     /// @returns the assembled SPIR-V
-    std::vector<uint32_t>& result() { return out_; }
+    std::vector<uint32_t>& Result() { return out_; }
 
   private:
     void process_instruction(const Instruction& inst);
diff --git a/src/tint/writer/spirv/binary_writer_test.cc b/src/tint/writer/spirv/binary_writer_test.cc
index c043b25..45210f6 100644
--- a/src/tint/writer/spirv/binary_writer_test.cc
+++ b/src/tint/writer/spirv/binary_writer_test.cc
@@ -23,7 +23,7 @@
     BinaryWriter bw;
     bw.WriteHeader(5);
 
-    auto res = bw.result();
+    auto res = bw.Result();
     ASSERT_EQ(res.size(), 5u);
     EXPECT_EQ(res[0], spv::MagicNumber);
     EXPECT_EQ(res[1], 0x00010300u);  // SPIR-V 1.3
@@ -39,7 +39,7 @@
     BinaryWriter bw;
     bw.WriteModule(&m);
 
-    auto res = bw.result();
+    auto res = bw.Result();
     ASSERT_EQ(res.size(), 2u);
     float f;
     memcpy(&f, res.data() + 1, 4);
@@ -53,7 +53,7 @@
     BinaryWriter bw;
     bw.WriteModule(&m);
 
-    auto res = bw.result();
+    auto res = bw.Result();
     ASSERT_EQ(res.size(), 2u);
     EXPECT_EQ(res[1], 2u);
 }
@@ -65,7 +65,7 @@
     BinaryWriter bw;
     bw.WriteModule(&m);
 
-    auto res = bw.result();
+    auto res = bw.Result();
     ASSERT_EQ(res.size(), 4u);
 
     uint8_t* v = reinterpret_cast<uint8_t*>(res.data() + 1);
@@ -90,7 +90,7 @@
     BinaryWriter bw;
     bw.WriteModule(&m);
 
-    auto res = bw.result();
+    auto res = bw.Result();
     ASSERT_EQ(res.size(), 4u);
 
     uint8_t* v = reinterpret_cast<uint8_t*>(res.data() + 1);
@@ -116,7 +116,7 @@
     bw.WriteInstruction(i1);
     bw.WriteInstruction(i2);
 
-    auto res = bw.result();
+    auto res = bw.Result();
     ASSERT_EQ(res.size(), 4u);
     EXPECT_EQ(res[1], 2u);
     EXPECT_EQ(res[3], 4u);
diff --git a/src/tint/writer/spirv/generator_impl.h b/src/tint/writer/spirv/generator_impl.h
index 3fd745d..52b7bc4 100644
--- a/src/tint/writer/spirv/generator_impl.h
+++ b/src/tint/writer/spirv/generator_impl.h
@@ -49,7 +49,7 @@
     bool Generate();
 
     /// @returns the result data
-    const std::vector<uint32_t>& Result() const { return writer_.result(); }
+    const std::vector<uint32_t>& Result() const { return writer_.Result(); }
 
     /// @returns the list of diagnostics raised by the generator
     diag::List Diagnostics() const { return builder_.Diagnostics(); }
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir.cc b/src/tint/writer/spirv/ir/generator_impl_ir.cc
index 0166177..4f07640 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir.cc
@@ -196,6 +196,13 @@
                 }
                 module_.PushType(spv::Op::OpConstantComposite, operands);
             },
+            [&](const type::Struct* str) {
+                OperandList operands = {Type(ty), id};
+                for (uint32_t i = 0; i < str->Members().Length(); i++) {
+                    operands.push_back(Constant(constant->Index(i)));
+                }
+                module_.PushType(spv::Op::OpConstantComposite, operands);
+            },
             [&](Default) {
                 TINT_ICE(Writer, diagnostics_) << "unhandled constant type: " << ty->FriendlyName();
             });
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir.h b/src/tint/writer/spirv/ir/generator_impl_ir.h
index 357c732..d0dc4bd 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir.h
+++ b/src/tint/writer/spirv/ir/generator_impl_ir.h
@@ -75,7 +75,7 @@
     spirv::Module& Module() { return module_; }
 
     /// @returns the generated SPIR-V binary data
-    const std::vector<uint32_t>& Result() const { return writer_.result(); }
+    const std::vector<uint32_t>& Result() const { return writer_.Result(); }
 
     /// @returns the list of diagnostics raised by the generator
     diag::List Diagnostics() const { return diagnostics_; }
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_constant_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_constant_test.cc
index b0b7665..40fae96 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_constant_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_constant_test.cc
@@ -245,6 +245,29 @@
 )");
 }
 
+TEST_F(SpvGeneratorImplTest, Struct) {
+    auto* str_ty = ty.Struct(mod.symbols.New("MyStruct"), {
+                                                              {mod.symbols.New("a"), ty.i32()},
+                                                              {mod.symbols.New("b"), ty.u32()},
+                                                              {mod.symbols.New("c"), ty.f32()},
+                                                          });
+    auto* str = mod.constant_values.Composite(str_ty, utils::Vector{
+                                                          mod.constant_values.Get(1_i),
+                                                          mod.constant_values.Get(2_u),
+                                                          mod.constant_values.Get(3_f),
+                                                      });
+    generator_.Constant(b.Constant(str));
+    EXPECT_EQ(DumpTypes(), R"(%3 = OpTypeInt 32 1
+%4 = OpTypeInt 32 0
+%5 = OpTypeFloat 32
+%2 = OpTypeStruct %3 %4 %5
+%6 = OpConstant %3 1
+%7 = OpConstant %4 2
+%8 = OpConstant %5 3
+%1 = OpConstantComposite %2 %6 %7 %8
+)");
+}
+
 // Test that we do not emit the same constant more than once.
 TEST_F(SpvGeneratorImplTest, Constant_Deduplicate) {
     generator_.Constant(b.Constant(i32(42)));
diff --git a/src/tint/writer/spirv/spv_dump.cc b/src/tint/writer/spirv/spv_dump.cc
index 9a63786..da24446 100644
--- a/src/tint/writer/spirv/spv_dump.cc
+++ b/src/tint/writer/spirv/spv_dump.cc
@@ -63,14 +63,14 @@
     BinaryWriter writer;
     writer.WriteHeader(module.IdBound());
     writer.WriteModule(&module);
-    return Disassemble(writer.result());
+    return Disassemble(writer.Result());
 }
 
 std::string DumpInstruction(const Instruction& inst) {
     BinaryWriter writer;
     writer.WriteHeader(kDefaultMaxIdBound);
     writer.WriteInstruction(inst);
-    return Disassemble(writer.result());
+    return Disassemble(writer.Result());
 }
 
 std::string DumpInstructions(const InstructionList& insts) {
@@ -79,7 +79,7 @@
     for (const auto& inst : insts) {
         writer.WriteInstruction(inst);
     }
-    return Disassemble(writer.result());
+    return Disassemble(writer.Result());
 }
 
 }  // namespace tint::writer::spirv
diff --git a/src/tint/writer/spirv/test_helper.h b/src/tint/writer/spirv/test_helper.h
index d030523..08111d8 100644
--- a/src/tint/writer/spirv/test_helper.h
+++ b/src/tint/writer/spirv/test_helper.h
@@ -96,7 +96,7 @@
         BinaryWriter writer;
         writer.WriteHeader(b.Module().IdBound());
         writer.WriteModule(&b.Module());
-        auto binary = writer.result();
+        auto binary = writer.Result();
 
         std::string spv_errors;
         auto msg_consumer = [&spv_errors](spv_message_level_t level, const char*,
diff --git a/src/tint/writer/syntax_tree/generator.cc b/src/tint/writer/syntax_tree/generator.cc
index 0f93ae5..5011244 100644
--- a/src/tint/writer/syntax_tree/generator.cc
+++ b/src/tint/writer/syntax_tree/generator.cc
@@ -29,7 +29,7 @@
     impl->Generate();
     result.success = impl->Diagnostics().empty();
     result.error = impl->Diagnostics().str();
-    result.ast = impl->result();
+    result.ast = impl->Result();
 
     return result;
 }
diff --git a/src/tint/writer/syntax_tree/generator_impl.cc b/src/tint/writer/syntax_tree/generator_impl.cc
index e8e58a3..4574c14 100644
--- a/src/tint/writer/syntax_tree/generator_impl.cc
+++ b/src/tint/writer/syntax_tree/generator_impl.cc
@@ -59,18 +59,18 @@
             [&](Default) { TINT_UNREACHABLE(Writer, diagnostics_); });
 
         if (decl != program_->AST().GlobalDeclarations().Back()) {
-            line();
+            Line();
         }
     }
 }
 
 void GeneratorImpl::EmitDiagnosticControl(const ast::DiagnosticControl& diagnostic) {
-    line() << "DiagnosticControl [severity: " << diagnostic.severity
+    Line() << "DiagnosticControl [severity: " << diagnostic.severity
            << ", rule: " << diagnostic.rule_name->String() << "]";
 }
 
 void GeneratorImpl::EmitEnable(const ast::Enable* enable) {
-    auto l = line();
+    auto l = Line();
     l << "Enable [";
     for (auto* ext : enable->extensions) {
         if (ext != enable->extensions.Front()) {
@@ -85,18 +85,18 @@
     Switch(
         ty,  //
         [&](const ast::Alias* alias) {
-            line() << "Alias [";
+            Line() << "Alias [";
             {
                 ScopedIndent ai(this);
 
-                line() << "name: " << alias->name->symbol.Name();
-                line() << "expr: ";
+                Line() << "name: " << alias->name->symbol.Name();
+                Line() << "expr: ";
                 {
                     ScopedIndent ex(this);
                     EmitExpression(alias->type);
                 }
             }
-            line() << "]";
+            Line() << "]";
         },
         [&](const ast::Struct* str) { EmitStructType(str); },
         [&](Default) {
@@ -115,234 +115,234 @@
         [&](const ast::IdentifierExpression* i) { EmitIdentifier(i); },
         [&](const ast::LiteralExpression* l) { EmitLiteral(l); },
         [&](const ast::MemberAccessorExpression* m) { EmitMemberAccessor(m); },
-        [&](const ast::PhonyExpression*) { line() << "[PhonyExpression]"; },
+        [&](const ast::PhonyExpression*) { Line() << "[PhonyExpression]"; },
         [&](const ast::UnaryOpExpression* u) { EmitUnaryOp(u); },
         [&](Default) { diagnostics_.add_error(diag::System::Writer, "unknown expression type"); });
 }
 
 void GeneratorImpl::EmitIndexAccessor(const ast::IndexAccessorExpression* expr) {
-    line() << "IndexAccessorExpression [";
+    Line() << "IndexAccessorExpression [";
     {
         ScopedIndent iae(this);
-        line() << "object: ";
+        Line() << "object: ";
         {
             ScopedIndent obj(this);
             EmitExpression(expr->object);
         }
 
-        line() << "index: ";
+        Line() << "index: ";
         {
             ScopedIndent idx(this);
             EmitExpression(expr->index);
         }
     }
-    line() << "]";
+    Line() << "]";
 }
 
 void GeneratorImpl::EmitMemberAccessor(const ast::MemberAccessorExpression* expr) {
-    line() << "MemberAccessorExpression [";
+    Line() << "MemberAccessorExpression [";
     {
         ScopedIndent mae(this);
 
-        line() << "object: ";
+        Line() << "object: ";
         {
             ScopedIndent obj(this);
             EmitExpression(expr->object);
         }
-        line() << "member: " << expr->member->symbol.Name();
+        Line() << "member: " << expr->member->symbol.Name();
     }
-    line() << "]";
+    Line() << "]";
 }
 
 void GeneratorImpl::EmitBitcast(const ast::BitcastExpression* expr) {
-    line() << "BitcastExpression [";
+    Line() << "BitcastExpression [";
     {
         ScopedIndent bc(this);
         {
-            line() << "type: ";
+            Line() << "type: ";
             ScopedIndent ty(this);
             EmitExpression(expr->type);
         }
         {
-            line() << "expr: ";
+            Line() << "expr: ";
             ScopedIndent exp(this);
             EmitExpression(expr->expr);
         }
     }
-    line() << "]";
+    Line() << "]";
 }
 
 void GeneratorImpl::EmitCall(const ast::CallExpression* expr) {
-    line() << "Call [";
+    Line() << "Call [";
     {
         ScopedIndent cl(this);
 
-        line() << "target: [";
+        Line() << "target: [";
         {
             ScopedIndent tgt(this);
             EmitExpression(expr->target);
         }
-        line() << "]";
+        Line() << "]";
 
         if (!expr->args.IsEmpty()) {
-            line() << "args: [";
+            Line() << "args: [";
             {
                 ScopedIndent args(this);
                 for (auto* arg : expr->args) {
-                    line() << "arg: [";
+                    Line() << "arg: [";
                     {
                         ScopedIndent arg_val(this);
                         EmitExpression(arg);
                     }
-                    line() << "]";
+                    Line() << "]";
                 }
             }
-            line() << "]";
+            Line() << "]";
         }
     }
-    line() << "]";
+    Line() << "]";
 }
 
 void GeneratorImpl::EmitLiteral(const ast::LiteralExpression* lit) {
-    line() << "LiteralExpression [";
+    Line() << "LiteralExpression [";
     {
         ScopedIndent le(this);
         Switch(
             lit,  //
-            [&](const ast::BoolLiteralExpression* l) { line() << (l->value ? "true" : "false"); },
+            [&](const ast::BoolLiteralExpression* l) { Line() << (l->value ? "true" : "false"); },
             [&](const ast::FloatLiteralExpression* l) {
                 // f16 literals are also emitted as float value with suffix "h".
                 // Note that all normal and subnormal f16 values are normal f32 values, and since
                 // NaN and Inf are not allowed to be spelled in literal, it should be fine to emit
                 // f16 literals in this way.
                 if (l->suffix == ast::FloatLiteralExpression::Suffix::kNone) {
-                    line() << DoubleToBitPreservingString(l->value);
+                    Line() << DoubleToBitPreservingString(l->value);
                 } else {
-                    line() << FloatToBitPreservingString(static_cast<float>(l->value)) << l->suffix;
+                    Line() << FloatToBitPreservingString(static_cast<float>(l->value)) << l->suffix;
                 }
             },
-            [&](const ast::IntLiteralExpression* l) { line() << l->value << l->suffix; },
+            [&](const ast::IntLiteralExpression* l) { Line() << l->value << l->suffix; },
             [&](Default) { diagnostics_.add_error(diag::System::Writer, "unknown literal type"); });
     }
-    line() << "]";
+    Line() << "]";
 }
 
 void GeneratorImpl::EmitIdentifier(const ast::IdentifierExpression* expr) {
-    line() << "IdentifierExpression [";
+    Line() << "IdentifierExpression [";
     {
         ScopedIndent ie(this);
         EmitIdentifier(expr->identifier);
     }
-    line() << "]";
+    Line() << "]";
 }
 
 void GeneratorImpl::EmitIdentifier(const ast::Identifier* ident) {
-    line() << "Identifier [";
+    Line() << "Identifier [";
     {
         ScopedIndent id(this);
         if (auto* tmpl_ident = ident->As<ast::TemplatedIdentifier>()) {
-            line() << "Templated [";
+            Line() << "Templated [";
             {
                 ScopedIndent tmpl(this);
                 if (!tmpl_ident->attributes.IsEmpty()) {
-                    line() << "attrs: [";
+                    Line() << "attrs: [";
                     {
                         ScopedIndent attrs(this);
                         EmitAttributes(tmpl_ident->attributes);
                     }
-                    line() << "]";
+                    Line() << "]";
                 }
-                line() << "name: " << ident->symbol.Name();
+                Line() << "name: " << ident->symbol.Name();
                 if (!tmpl_ident->arguments.IsEmpty()) {
-                    line() << "args: [";
+                    Line() << "args: [";
                     {
                         ScopedIndent args(this);
                         for (auto* expr : tmpl_ident->arguments) {
                             EmitExpression(expr);
                         }
                     }
-                    line() << "]";
+                    Line() << "]";
                 }
             }
-            line() << "]";
+            Line() << "]";
         } else {
-            line() << ident->symbol.Name();
+            Line() << ident->symbol.Name();
         }
     }
-    line() << "]";
+    Line() << "]";
 }
 
 void GeneratorImpl::EmitFunction(const ast::Function* func) {
-    line() << "Function [";
+    Line() << "Function [";
     {
         ScopedIndent funct(this);
 
         if (func->attributes.Length()) {
-            line() << "attrs: [";
+            Line() << "attrs: [";
             {
                 ScopedIndent attrs(this);
                 EmitAttributes(func->attributes);
             }
-            line() << "]";
+            Line() << "]";
         }
-        line() << "name: " << func->name->symbol.Name();
+        Line() << "name: " << func->name->symbol.Name();
 
         if (!func->params.IsEmpty()) {
-            line() << "params: [";
+            Line() << "params: [";
             {
                 ScopedIndent args(this);
                 for (auto* v : func->params) {
-                    line() << "param: [";
+                    Line() << "param: [";
                     {
                         ScopedIndent param(this);
-                        line() << "name: " << v->name->symbol.Name();
+                        Line() << "name: " << v->name->symbol.Name();
                         if (!v->attributes.IsEmpty()) {
-                            line() << "attrs: [";
+                            Line() << "attrs: [";
                             {
                                 ScopedIndent attrs(this);
                                 EmitAttributes(v->attributes);
                             }
-                            line() << "]";
+                            Line() << "]";
                         }
-                        line() << "type: [";
+                        Line() << "type: [";
                         {
                             ScopedIndent ty(this);
                             EmitExpression(v->type);
                         }
-                        line() << "]";
+                        Line() << "]";
                     }
-                    line() << "]";
+                    Line() << "]";
                 }
             }
-            line() << "]";
+            Line() << "]";
         }
 
-        line() << "return: [";
+        Line() << "return: [";
         {
             ScopedIndent ret(this);
 
             if (func->return_type || !func->return_type_attributes.IsEmpty()) {
                 if (!func->return_type_attributes.IsEmpty()) {
-                    line() << "attrs: [";
+                    Line() << "attrs: [";
                     {
                         ScopedIndent attrs(this);
                         EmitAttributes(func->return_type_attributes);
                     }
-                    line() << "]";
+                    Line() << "]";
                 }
 
-                line() << "type: [";
+                Line() << "type: [";
                 {
                     ScopedIndent ty(this);
                     EmitExpression(func->return_type);
                 }
-                line() << "]";
+                Line() << "]";
             } else {
-                line() << "void";
+                Line() << "void";
             }
         }
-        line() << "]";
-        line() << "body: [";
+        Line() << "]";
+        Line() << "body: [";
         {
             ScopedIndent bdy(this);
             if (func->body) {
@@ -350,130 +350,130 @@
                 EmitStatementsWithIndent(func->body->statements);
             }
         }
-        line() << "]";
+        Line() << "]";
     }
-    line() << "]";
+    Line() << "]";
 }
 
 void GeneratorImpl::EmitImageFormat(const builtin::TexelFormat fmt) {
-    line() << "builtin::TexelFormat [" << fmt << "]";
+    Line() << "builtin::TexelFormat [" << fmt << "]";
 }
 
 void GeneratorImpl::EmitStructType(const ast::Struct* str) {
-    line() << "Struct [";
+    Line() << "Struct [";
     {
         ScopedIndent strct(this);
 
         if (str->attributes.Length()) {
-            line() << "attrs: [";
+            Line() << "attrs: [";
             {
                 ScopedIndent attrs(this);
                 EmitAttributes(str->attributes);
             }
-            line() << "]";
+            Line() << "]";
         }
-        line() << "name: " << str->name->symbol.Name();
-        line() << "members: [";
+        Line() << "name: " << str->name->symbol.Name();
+        Line() << "members: [";
         {
             ScopedIndent membs(this);
 
             for (auto* mem : str->members) {
-                line() << "StructMember[";
+                Line() << "StructMember[";
                 {
                     ScopedIndent m(this);
                     if (!mem->attributes.IsEmpty()) {
-                        line() << "attrs: [";
+                        Line() << "attrs: [";
                         {
                             ScopedIndent attrs(this);
                             EmitAttributes(mem->attributes);
                         }
-                        line() << "]";
+                        Line() << "]";
                     }
 
-                    line() << "name: " << mem->name->symbol.Name();
-                    line() << "type: [";
+                    Line() << "name: " << mem->name->symbol.Name();
+                    Line() << "type: [";
                     {
                         ScopedIndent ty(this);
                         EmitExpression(mem->type);
                     }
-                    line() << "]";
+                    Line() << "]";
                 }
             }
-            line() << "]";
+            Line() << "]";
         }
-        line() << "]";
+        Line() << "]";
     }
-    line() << "]";
+    Line() << "]";
 }
 
 void GeneratorImpl::EmitVariable(const ast::Variable* v) {
-    line() << "Variable [";
+    Line() << "Variable [";
     {
         ScopedIndent variable(this);
         if (!v->attributes.IsEmpty()) {
-            line() << "attrs: [";
+            Line() << "attrs: [";
             {
                 ScopedIndent attr(this);
                 EmitAttributes(v->attributes);
             }
-            line() << "]";
+            Line() << "]";
         }
 
         Switch(
             v,  //
             [&](const ast::Var* var) {
                 if (var->declared_address_space || var->declared_access) {
-                    line() << "Var [";
+                    Line() << "Var [";
                     {
                         ScopedIndent vr(this);
-                        line() << "address_space: [";
+                        Line() << "address_space: [";
                         {
                             ScopedIndent addr(this);
                             EmitExpression(var->declared_address_space);
                         }
-                        line() << "]";
+                        Line() << "]";
                         if (var->declared_access) {
-                            line() << "access: [";
+                            Line() << "access: [";
                             {
                                 ScopedIndent acs(this);
                                 EmitExpression(var->declared_access);
                             }
-                            line() << "]";
+                            Line() << "]";
                         }
                     }
-                    line() << "]";
+                    Line() << "]";
                 } else {
-                    line() << "Var []";
+                    Line() << "Var []";
                 }
             },
-            [&](const ast::Let*) { line() << "Let []"; },
-            [&](const ast::Override*) { line() << "Override []"; },
-            [&](const ast::Const*) { line() << "Const []"; },
+            [&](const ast::Let*) { Line() << "Let []"; },
+            [&](const ast::Override*) { Line() << "Override []"; },
+            [&](const ast::Const*) { Line() << "Const []"; },
             [&](Default) {
                 TINT_ICE(Writer, diagnostics_) << "unhandled variable type " << v->TypeInfo().name;
             });
 
-        line() << "name: " << v->name->symbol.Name();
+        Line() << "name: " << v->name->symbol.Name();
 
         if (auto ty = v->type) {
-            line() << "type: [";
+            Line() << "type: [";
             {
                 ScopedIndent vty(this);
                 EmitExpression(ty);
             }
-            line() << "]";
+            Line() << "]";
         }
 
         if (v->initializer != nullptr) {
-            line() << "initializer: [";
+            Line() << "initializer: [";
             {
                 ScopedIndent init(this);
                 EmitExpression(v->initializer);
             }
-            line() << "]";
+            Line() << "]";
         }
     }
-    line() << "]";
+    Line() << "]";
 }
 
 void GeneratorImpl::EmitAttributes(utils::VectorRef<const ast::Attribute*> attrs) {
@@ -482,7 +482,7 @@
             attr,  //
             [&](const ast::WorkgroupAttribute* workgroup) {
                 auto values = workgroup->Values();
-                line() << "WorkgroupAttribute [";
+                Line() << "WorkgroupAttribute [";
                 {
                     ScopedIndent wg(this);
                     for (size_t i = 0; i < 3; i++) {
@@ -491,106 +491,106 @@
                         }
                     }
                 }
-                line() << "]";
+                Line() << "]";
             },
             [&](const ast::StageAttribute* stage) {
-                line() << "StageAttribute [" << stage->stage << "]";
+                Line() << "StageAttribute [" << stage->stage << "]";
             },
             [&](const ast::BindingAttribute* binding) {
-                line() << "BindingAttribute [";
+                Line() << "BindingAttribute [";
                 {
                     ScopedIndent ba(this);
                     EmitExpression(binding->expr);
                 }
-                line() << "]";
+                Line() << "]";
             },
             [&](const ast::GroupAttribute* group) {
-                line() << "GroupAttribute [";
+                Line() << "GroupAttribute [";
                 {
                     ScopedIndent ga(this);
                     EmitExpression(group->expr);
                 }
-                line() << "]";
+                Line() << "]";
             },
             [&](const ast::LocationAttribute* location) {
-                line() << "LocationAttribute [";
+                Line() << "LocationAttribute [";
                 {
                     ScopedIndent la(this);
                     EmitExpression(location->expr);
                 }
-                line() << "]";
+                Line() << "]";
             },
             [&](const ast::BuiltinAttribute* builtin) {
-                line() << "BuiltinAttribute [";
+                Line() << "BuiltinAttribute [";
                 {
                     ScopedIndent ba(this);
                     EmitExpression(builtin->builtin);
                 }
-                line() << "]";
+                Line() << "]";
             },
             [&](const ast::DiagnosticAttribute* diagnostic) {
                 EmitDiagnosticControl(diagnostic->control);
             },
             [&](const ast::InterpolateAttribute* interpolate) {
-                line() << "InterpolateAttribute [";
+                Line() << "InterpolateAttribute [";
                 {
                     ScopedIndent ia(this);
-                    line() << "type: [";
+                    Line() << "type: [";
                     {
                         ScopedIndent ty(this);
                         EmitExpression(interpolate->type);
                     }
-                    line() << "]";
+                    Line() << "]";
                     if (interpolate->sampling) {
-                        line() << "sampling: [";
+                        Line() << "sampling: [";
                         {
                             ScopedIndent sa(this);
                             EmitExpression(interpolate->sampling);
                         }
-                        line() << "]";
+                        Line() << "]";
                     }
                 }
-                line() << "]";
+                Line() << "]";
             },
-            [&](const ast::InvariantAttribute*) { line() << "InvariantAttribute []"; },
+            [&](const ast::InvariantAttribute*) { Line() << "InvariantAttribute []"; },
             [&](const ast::IdAttribute* override_deco) {
-                line() << "IdAttribute [";
+                Line() << "IdAttribute [";
                 {
                     ScopedIndent id(this);
                     EmitExpression(override_deco->expr);
                 }
-                line() << "]";
+                Line() << "]";
             },
-            [&](const ast::MustUseAttribute*) { line() << "MustUseAttribute []"; },
+            [&](const ast::MustUseAttribute*) { Line() << "MustUseAttribute []"; },
             [&](const ast::StructMemberOffsetAttribute* offset) {
-                line() << "StructMemberOffsetAttribute [";
+                Line() << "StructMemberOffsetAttribute [";
                 {
                     ScopedIndent smoa(this);
                     EmitExpression(offset->expr);
                 }
-                line() << "]";
+                Line() << "]";
             },
             [&](const ast::StructMemberSizeAttribute* size) {
-                line() << "StructMemberSizeAttribute [";
+                Line() << "StructMemberSizeAttribute [";
                 {
                     ScopedIndent smsa(this);
                     EmitExpression(size->expr);
                 }
-                line() << "]";
+                Line() << "]";
             },
             [&](const ast::StructMemberAlignAttribute* align) {
-                line() << "StructMemberAlignAttribute [";
+                Line() << "StructMemberAlignAttribute [";
                 {
                     ScopedIndent smaa(this);
                     EmitExpression(align->expr);
                 }
-                line() << "]";
+                Line() << "]";
             },
             [&](const ast::StrideAttribute* stride) {
-                line() << "StrideAttribute [" << stride->stride << "]";
+                Line() << "StrideAttribute [" << stride->stride << "]";
             },
             [&](const ast::InternalAttribute* internal) {
-                line() << "InternalAttribute [" << internal->InternalName() << "]";
+                Line() << "InternalAttribute [" << internal->InternalName() << "]";
             },
             [&](Default) {
                 TINT_ICE(Writer, diagnostics_)
@@ -600,87 +600,87 @@
 }
 
 void GeneratorImpl::EmitBinary(const ast::BinaryExpression* expr) {
-    line() << "BinaryExpression [";
+    Line() << "BinaryExpression [";
     {
         ScopedIndent be(this);
-        line() << "lhs: [";
+        Line() << "lhs: [";
         {
             ScopedIndent lhs(this);
 
             EmitExpression(expr->lhs);
         }
-        line() << "]";
-        line() << "op: [";
+        Line() << "]";
+        Line() << "op: [";
         {
             ScopedIndent op(this);
             EmitBinaryOp(expr->op);
         }
-        line() << "]";
-        line() << "rhs: [";
+        Line() << "]";
+        Line() << "rhs: [";
         {
             ScopedIndent rhs(this);
             EmitExpression(expr->rhs);
         }
-        line() << "]";
+        Line() << "]";
     }
-    line() << "]";
+    Line() << "]";
 }
 
 void GeneratorImpl::EmitBinaryOp(const ast::BinaryOp op) {
     switch (op) {
         case ast::BinaryOp::kAnd:
-            line() << "&";
+            Line() << "&";
             break;
         case ast::BinaryOp::kOr:
-            line() << "|";
+            Line() << "|";
             break;
         case ast::BinaryOp::kXor:
-            line() << "^";
+            Line() << "^";
             break;
         case ast::BinaryOp::kLogicalAnd:
-            line() << "&&";
+            Line() << "&&";
             break;
         case ast::BinaryOp::kLogicalOr:
-            line() << "||";
+            Line() << "||";
             break;
         case ast::BinaryOp::kEqual:
-            line() << "==";
+            Line() << "==";
             break;
         case ast::BinaryOp::kNotEqual:
-            line() << "!=";
+            Line() << "!=";
             break;
         case ast::BinaryOp::kLessThan:
-            line() << "<";
+            Line() << "<";
             break;
         case ast::BinaryOp::kGreaterThan:
-            line() << ">";
+            Line() << ">";
             break;
         case ast::BinaryOp::kLessThanEqual:
-            line() << "<=";
+            Line() << "<=";
             break;
         case ast::BinaryOp::kGreaterThanEqual:
-            line() << ">=";
+            Line() << ">=";
             break;
         case ast::BinaryOp::kShiftLeft:
-            line() << "<<";
+            Line() << "<<";
             break;
         case ast::BinaryOp::kShiftRight:
-            line() << ">>";
+            Line() << ">>";
             break;
         case ast::BinaryOp::kAdd:
-            line() << "+";
+            Line() << "+";
             break;
         case ast::BinaryOp::kSubtract:
-            line() << "-";
+            Line() << "-";
             break;
         case ast::BinaryOp::kMultiply:
-            line() << "*";
+            Line() << "*";
             break;
         case ast::BinaryOp::kDivide:
-            line() << "/";
+            Line() << "/";
             break;
         case ast::BinaryOp::kModulo:
-            line() << "%";
+            Line() << "%";
             break;
         case ast::BinaryOp::kNone:
             diagnostics_.add_error(diag::System::Writer, "missing binary operation type");
@@ -689,39 +689,39 @@
 }
 
 void GeneratorImpl::EmitUnaryOp(const ast::UnaryOpExpression* expr) {
-    line() << "UnaryOpExpression [";
+    Line() << "UnaryOpExpression [";
     {
         ScopedIndent uoe(this);
-        line() << "op: [";
+        Line() << "op: [";
         {
             ScopedIndent op(this);
             switch (expr->op) {
                 case ast::UnaryOp::kAddressOf:
-                    line() << "&";
+                    Line() << "&";
                     break;
                 case ast::UnaryOp::kComplement:
-                    line() << "~";
+                    Line() << "~";
                     break;
                 case ast::UnaryOp::kIndirection:
-                    line() << "*";
+                    Line() << "*";
                     break;
                 case ast::UnaryOp::kNot:
-                    line() << "!";
+                    Line() << "!";
                     break;
                 case ast::UnaryOp::kNegation:
-                    line() << "-";
+                    Line() << "-";
                     break;
             }
         }
-        line() << "]";
-        line() << "expr: [";
+        Line() << "]";
+        Line() << "expr: [";
         {
             ScopedIndent ex(this);
             EmitExpression(expr->expr);
         }
-        line() << "]";
+        Line() << "]";
     }
-    line() << "]";
+    Line() << "]";
 }
 
 void GeneratorImpl::EmitBlock(const ast::BlockStatement* stmt) {
@@ -731,12 +731,12 @@
 
 void GeneratorImpl::EmitBlockHeader(const ast::BlockStatement* stmt) {
     if (!stmt->attributes.IsEmpty()) {
-        line() << "attrs: [";
+        Line() << "attrs: [";
         {
             ScopedIndent attrs(this);
             EmitAttributes(stmt->attributes);
         }
-        line() << "]";
+        Line() << "]";
     }
 }
 
@@ -778,111 +778,111 @@
 }
 
 void GeneratorImpl::EmitAssign(const ast::AssignmentStatement* stmt) {
-    line() << "AssignmentStatement [";
+    Line() << "AssignmentStatement [";
     {
         ScopedIndent as(this);
-        line() << "lhs: [";
+        Line() << "lhs: [";
         {
             ScopedIndent lhs(this);
             EmitExpression(stmt->lhs);
         }
-        line() << "]";
-        line() << "rhs: [";
+        Line() << "]";
+        Line() << "rhs: [";
         {
             ScopedIndent rhs(this);
             EmitExpression(stmt->rhs);
         }
-        line() << "]";
+        Line() << "]";
     }
-    line() << "]";
+    Line() << "]";
 }
 
 void GeneratorImpl::EmitBreak(const ast::BreakStatement*) {
-    line() << "BreakStatement []";
+    Line() << "BreakStatement []";
 }
 
 void GeneratorImpl::EmitBreakIf(const ast::BreakIfStatement* b) {
-    line() << "BreakIfStatement [";
+    Line() << "BreakIfStatement [";
     {
         ScopedIndent bis(this);
         EmitExpression(b->condition);
     }
-    line() << "]";
+    Line() << "]";
 }
 
 void GeneratorImpl::EmitCase(const ast::CaseStatement* stmt) {
-    line() << "CaseStatement [";
+    Line() << "CaseStatement [";
     {
         ScopedIndent cs(this);
         if (stmt->selectors.Length() == 1 && stmt->ContainsDefault()) {
-            line() << "selector: default";
+            Line() << "selector: default";
             EmitBlockHeader(stmt->body);
         } else {
-            line() << "selectors: [";
+            Line() << "selectors: [";
             {
                 ScopedIndent sels(this);
                 for (auto* sel : stmt->selectors) {
                     if (sel->IsDefault()) {
-                        line() << "default []";
+                        Line() << "default []";
                     } else {
                         EmitExpression(sel->expr);
                     }
                 }
             }
-            line() << "]";
+            Line() << "]";
             EmitBlockHeader(stmt->body);
         }
         EmitStatementsWithIndent(stmt->body->statements);
     }
-    line() << "]";
+    Line() << "]";
 }
 
 void GeneratorImpl::EmitCompoundAssign(const ast::CompoundAssignmentStatement* stmt) {
-    line() << "CompoundAssignmentStatement [";
+    Line() << "CompoundAssignmentStatement [";
     {
         ScopedIndent cas(this);
-        line() << "lhs: [";
+        Line() << "lhs: [";
         {
             ScopedIndent lhs(this);
             EmitExpression(stmt->lhs);
         }
-        line() << "]";
+        Line() << "]";
 
-        line() << "op: [";
+        Line() << "op: [";
         {
             ScopedIndent op(this);
             EmitBinaryOp(stmt->op);
         }
-        line() << "]";
-        line() << "rhs: [";
+        Line() << "]";
+        Line() << "rhs: [";
         {
             ScopedIndent rhs(this);
 
             EmitExpression(stmt->rhs);
         }
-        line() << "]";
+        Line() << "]";
     }
-    line() << "]";
+    Line() << "]";
 }
 
 void GeneratorImpl::EmitContinue(const ast::ContinueStatement*) {
-    line() << "ContinueStatement []";
+    Line() << "ContinueStatement []";
 }
 
 void GeneratorImpl::EmitIf(const ast::IfStatement* stmt) {
     {
-        line() << "IfStatement [";
+        Line() << "IfStatement [";
         {
             ScopedIndent ifs(this);
-            line() << "condition: [";
+            Line() << "condition: [";
             {
                 ScopedIndent cond(this);
                 EmitExpression(stmt->condition);
             }
-            line() << "]";
+            Line() << "]";
             EmitBlockHeader(stmt->body);
         }
-        line() << "] ";
+        Line() << "] ";
     }
     EmitStatementsWithIndent(stmt->body->statements);
 
@@ -890,27 +890,27 @@
     while (e) {
         if (auto* elseif = e->As<ast::IfStatement>()) {
             {
-                line() << "Else IfStatement [";
+                Line() << "Else IfStatement [";
                 {
                     ScopedIndent ifs(this);
-                    line() << "condition: [";
+                    Line() << "condition: [";
                     EmitExpression(elseif->condition);
                 }
-                line() << "]";
+                Line() << "]";
                 EmitBlockHeader(elseif->body);
             }
-            line() << "]";
+            Line() << "]";
             EmitStatementsWithIndent(elseif->body->statements);
             e = elseif->else_statement;
         } else {
             auto* body = e->As<ast::BlockStatement>();
             {
-                line() << "Else [";
+                Line() << "Else [";
                 {
                     ScopedIndent els(this);
                     EmitBlockHeader(body);
                 }
-                line() << "]";
+                Line() << "]";
             }
             EmitStatementsWithIndent(body->statements);
             break;
@@ -919,37 +919,37 @@
 }
 
 void GeneratorImpl::EmitIncrementDecrement(const ast::IncrementDecrementStatement* stmt) {
-    line() << "IncrementDecrementStatement [";
+    Line() << "IncrementDecrementStatement [";
     {
         ScopedIndent ids(this);
-        line() << "expr: [";
+        Line() << "expr: [";
         EmitExpression(stmt->lhs);
-        line() << "]";
-        line() << "dir: " << (stmt->increment ? "++" : "--");
+        Line() << "]";
+        Line() << "dir: " << (stmt->increment ? "++" : "--");
     }
-    line() << "]";
+    Line() << "]";
 }
 
 void GeneratorImpl::EmitDiscard(const ast::DiscardStatement*) {
-    line() << "DiscardStatement []";
+    Line() << "DiscardStatement []";
 }
 
 void GeneratorImpl::EmitLoop(const ast::LoopStatement* stmt) {
-    line() << "LoopStatement [";
+    Line() << "LoopStatement [";
     {
         ScopedIndent ls(this);
         EmitStatements(stmt->body->statements);
 
         if (stmt->continuing && !stmt->continuing->Empty()) {
-            line() << "Continuing [";
+            Line() << "Continuing [";
             {
                 ScopedIndent cont(this);
                 EmitStatementsWithIndent(stmt->continuing->statements);
             }
-            line() << "]";
+            Line() << "]";
         }
     }
-    line() << "]";
+    Line() << "]";
 }
 
 void GeneratorImpl::EmitForLoop(const ast::ForLoopStatement* stmt) {
@@ -965,30 +965,30 @@
         EmitStatement(cont);
     }
 
-    line() << "ForLoopStatement [";
+    Line() << "ForLoopStatement [";
     {
         ScopedIndent fs(this);
 
-        line() << "initializer: [";
+        Line() << "initializer: [";
         {
             ScopedIndent init(this);
             switch (init_buf.lines.size()) {
                 case 0:  // No initializer
                     break;
                 case 1:  // Single line initializer statement
-                    line() << utils::TrimSuffix(init_buf.lines[0].content, ";");
+                    Line() << utils::TrimSuffix(init_buf.lines[0].content, ";");
                     break;
                 default:  // Block initializer statement
                     for (size_t i = 1; i < init_buf.lines.size(); i++) {
                         // Indent all by the first line
                         init_buf.lines[i].indent += current_buffer_->current_indent;
                     }
-                    line() << utils::TrimSuffix(init_buf.String(), "\n");
+                    Line() << utils::TrimSuffix(init_buf.String(), "\n");
                     break;
             }
         }
-        line() << "]";
-        line() << "condition: [";
+        Line() << "]";
+        Line() << "condition: [";
         {
             ScopedIndent con(this);
             if (auto* cond = stmt->condition) {
@@ -996,72 +996,72 @@
             }
         }
 
-        line() << "]";
-        line() << "continuing: [";
+        Line() << "]";
+        Line() << "continuing: [";
         {
             ScopedIndent cont(this);
             switch (cont_buf.lines.size()) {
                 case 0:  // No continuing
                     break;
                 case 1:  // Single line continuing statement
-                    line() << utils::TrimSuffix(cont_buf.lines[0].content, ";");
+                    Line() << utils::TrimSuffix(cont_buf.lines[0].content, ";");
                     break;
                 default:  // Block continuing statement
                     for (size_t i = 1; i < cont_buf.lines.size(); i++) {
                         // Indent all by the first line
                         cont_buf.lines[i].indent += current_buffer_->current_indent;
                     }
-                    line() << utils::TrimSuffix(cont_buf.String(), "\n");
+                    Line() << utils::TrimSuffix(cont_buf.String(), "\n");
                     break;
             }
         }
         EmitBlockHeader(stmt->body);
         EmitStatementsWithIndent(stmt->body->statements);
     }
-    line() << "]";
+    Line() << "]";
 }
 
 void GeneratorImpl::EmitWhile(const ast::WhileStatement* stmt) {
-    line() << "WhileStatement [";
+    Line() << "WhileStatement [";
     {
         ScopedIndent ws(this);
         EmitExpression(stmt->condition);
         EmitBlockHeader(stmt->body);
         EmitStatementsWithIndent(stmt->body->statements);
     }
-    line() << "]";
+    Line() << "]";
 }
 
 void GeneratorImpl::EmitReturn(const ast::ReturnStatement* stmt) {
-    line() << "ReturnStatement [";
+    Line() << "ReturnStatement [";
     {
         ScopedIndent ret(this);
         if (stmt->value) {
             EmitExpression(stmt->value);
         }
     }
-    line() << "]";
+    Line() << "]";
 }
 
 void GeneratorImpl::EmitConstAssert(const ast::ConstAssert* stmt) {
-    line() << "ConstAssert [";
+    Line() << "ConstAssert [";
     {
         ScopedIndent ca(this);
         EmitExpression(stmt->condition);
     }
-    line() << "]";
+    Line() << "]";
 }
 
 void GeneratorImpl::EmitSwitch(const ast::SwitchStatement* stmt) {
-    line() << "SwitchStatement [";
+    Line() << "SwitchStatement [";
     {
         ScopedIndent ss(this);
-        line() << "condition: [";
+        Line() << "condition: [";
         {
             ScopedIndent cond(this);
             EmitExpression(stmt->condition);
         }
-        line() << "]";
+        Line() << "]";
 
         {
             ScopedIndent si(this);
@@ -1070,7 +1070,7 @@
             }
         }
     }
-    line() << "]";
+    Line() << "]";
 }
 
 }  // namespace tint::writer::syntax_tree
diff --git a/src/tint/writer/syntax_tree/generator_impl.h b/src/tint/writer/syntax_tree/generator_impl.h
index 2473df2..4ffed4a 100644
--- a/src/tint/writer/syntax_tree/generator_impl.h
+++ b/src/tint/writer/syntax_tree/generator_impl.h
@@ -46,7 +46,7 @@
     /// Constructor
     /// @param program the program
     explicit GeneratorImpl(const Program* program);
-    ~GeneratorImpl();
+    ~GeneratorImpl() override;
 
     /// Generates the result data
     void Generate();
diff --git a/src/tint/writer/text.h b/src/tint/writer/text.h
index 2bbf1c2..0590eba 100644
--- a/src/tint/writer/text.h
+++ b/src/tint/writer/text.h
@@ -27,7 +27,7 @@
     ~Text() override;
 
     /// @returns the result data
-    virtual std::string result() const = 0;
+    virtual std::string Result() const = 0;
 };
 
 }  // namespace tint::writer
diff --git a/src/tint/writer/text_generator.cc b/src/tint/writer/text_generator.cc
index 89e1a6f..1585e79 100644
--- a/src/tint/writer/text_generator.cc
+++ b/src/tint/writer/text_generator.cc
@@ -18,6 +18,7 @@
 #include <limits>
 
 #include "src/tint/debug.h"
+#include "src/tint/utils/map.h"
 
 namespace tint::writer {
 
@@ -25,6 +26,15 @@
 
 TextGenerator::~TextGenerator() = default;
 
+std::string TextGenerator::StructName(const type::Struct* s) {
+    auto name = s->Name().Name();
+    if (name.size() > 1 && name[0] == '_' && name[1] == '_') {
+        name = utils::GetOrCreate(builtin_struct_names_, s,
+                                  [&] { return UniqueIdentifier(name.substr(2)); });
+    }
+    return name;
+}
+
 TextGenerator::LineWriter::LineWriter(TextBuffer* buf) : buffer(buf) {}
 
 TextGenerator::LineWriter::LineWriter(LineWriter&& other) {
@@ -50,7 +60,7 @@
 }
 
 void TextGenerator::TextBuffer::Append(const std::string& line) {
-    lines.emplace_back(Line{current_indent, line});
+    lines.emplace_back(LineInfo{current_indent, line});
 }
 
 void TextGenerator::TextBuffer::Insert(const std::string& line, size_t before, uint32_t indent) {
@@ -62,13 +72,13 @@
         return;
     }
     using DT = decltype(lines)::difference_type;
-    lines.insert(lines.begin() + static_cast<DT>(before), Line{indent, line});
+    lines.insert(lines.begin() + static_cast<DT>(before), LineInfo{indent, line});
 }
 
 void TextGenerator::TextBuffer::Append(const TextBuffer& tb) {
     for (auto& line : tb.lines) {
         // TODO(bclayton): inefficient, consider optimizing
-        lines.emplace_back(Line{current_indent + line.indent, line.content});
+        lines.emplace_back(LineInfo{current_indent + line.indent, line.content});
     }
 }
 
@@ -85,7 +95,7 @@
         // TODO(bclayton): inefficient, consider optimizing
         using DT = decltype(lines)::difference_type;
         lines.insert(lines.begin() + static_cast<DT>(before + idx),
-                     Line{indent + line.indent, line.content});
+                     LineInfo{indent + line.indent, line.content});
         idx++;
     }
 }
diff --git a/src/tint/writer/text_generator.h b/src/tint/writer/text_generator.h
index 8458db0..348a31b 100644
--- a/src/tint/writer/text_generator.h
+++ b/src/tint/writer/text_generator.h
@@ -21,6 +21,7 @@
 #include <vector>
 
 #include "src/tint/diagnostic/diagnostic.h"
+#include "src/tint/type/struct.h"
 #include "src/tint/utils/string_stream.h"
 
 namespace tint::writer {
@@ -28,8 +29,8 @@
 /// Helper methods for generators which are creating text output
 class TextGenerator {
   public:
-    /// Line holds a single line of text
-    struct Line {
+    /// LineInfo holds a single line of text
+    struct LineInfo {
         /// The indentation of the line in blankspace
         uint32_t indent = 0;
         /// The content of the line, without a trailing newline character
@@ -82,25 +83,8 @@
         uint32_t current_indent = 0;
 
         /// The lines
-        std::vector<Line> lines;
+        std::vector<LineInfo> lines;
     };
-
-    /// Constructor
-    TextGenerator();
-    ~TextGenerator();
-
-    /// Increment the emitter indent level
-    void increment_indent() { current_buffer_->IncrementIndent(); }
-    /// Decrement the emitter indent level
-    void decrement_indent() { current_buffer_->DecrementIndent(); }
-
-    /// @returns the result data
-    std::string result() const { return main_buffer_.String(); }
-
-    /// @returns the list of diagnostics raised by the generator.
-    const diag::List& Diagnostics() const { return diagnostics_; }
-
-  protected:
     /// LineWriter is a helper that acts as a string buffer, who's content is
     /// emitted to the TextBuffer as a single line on destruction.
     struct LineWriter {
@@ -134,6 +118,37 @@
         TextBuffer* buffer;
     };
 
+    /// Increment the emitter indent level
+    void IncrementIndent() { current_buffer_->IncrementIndent(); }
+    /// Decrement the emitter indent level
+    void DecrementIndent() { current_buffer_->DecrementIndent(); }
+
+    /// @returns a new LineWriter, used for buffering and writing a line to
+    /// the end of #current_buffer_.
+    LineWriter Line() { return LineWriter(current_buffer_); }
+    /// @param buffer the TextBuffer to write the line to
+    /// @returns a new LineWriter, used for buffering and writing a line to
+    /// the end of `buffer`.
+    static LineWriter Line(TextBuffer* buffer) { return LineWriter(buffer); }
+
+    /// @return a new, unique identifier with the given prefix.
+    /// @param prefix optional prefix to apply to the generated identifier. If
+    /// empty "tint_symbol" will be used.
+    virtual std::string UniqueIdentifier(const std::string& prefix = "") = 0;
+
+    /// @param s the structure
+    /// @returns the name of the structure, taking special care of builtin structures that start
+    /// with double underscores. If the structure is a builtin, then the returned name will be a
+    /// unique name without the leading underscores.
+    std::string StructName(const type::Struct* s);
+
+    /// @returns the result data
+    virtual std::string Result() const { return main_buffer_.String(); }
+
+    /// @returns the list of diagnostics raised by the generator.
+    const diag::List& Diagnostics() const { return diagnostics_; }
+
+  protected:
     /// Helper for writing a '(' on construction and a ')' destruction.
     struct ScopedParen {
         /// Constructor
@@ -169,23 +184,21 @@
         TextBuffer* buffer_;
     };
 
-    /// @returns a new LineWriter, used for buffering and writing a line to
-    /// the end of #current_buffer_.
-    LineWriter line() { return LineWriter(current_buffer_); }
-
-    /// @param buffer the TextBuffer to write the line to
-    /// @returns a new LineWriter, used for buffering and writing a line to
-    /// the end of `buffer`.
-    static LineWriter line(TextBuffer* buffer) { return LineWriter(buffer); }
+    /// Constructor
+    TextGenerator();
+    virtual ~TextGenerator();
 
     /// Diagnostics generated by the generator
     diag::List diagnostics_;
     /// The buffer the TextGenerator is currently appending lines to
     TextBuffer* current_buffer_ = &main_buffer_;
 
-  private:
     /// The primary text buffer that the generator will emit
     TextBuffer main_buffer_;
+
+  private:
+    /// Map of builtin structure to unique generated name
+    std::unordered_map<const type::Struct*, std::string> builtin_struct_names_;
 };
 
 }  // namespace tint::writer
diff --git a/src/tint/writer/wgsl/generator.cc b/src/tint/writer/wgsl/generator.cc
index f1f3f68..4d4f2c1 100644
--- a/src/tint/writer/wgsl/generator.cc
+++ b/src/tint/writer/wgsl/generator.cc
@@ -29,7 +29,7 @@
     impl->Generate();
     result.success = impl->Diagnostics().empty();
     result.error = impl->Diagnostics().str();
-    result.wgsl = impl->result();
+    result.wgsl = impl->Result();
 
     return result;
 }
diff --git a/src/tint/writer/wgsl/generator_impl.cc b/src/tint/writer/wgsl/generator_impl.cc
index 751d16f..59aa35c 100644
--- a/src/tint/writer/wgsl/generator_impl.cc
+++ b/src/tint/writer/wgsl/generator_impl.cc
@@ -54,13 +54,13 @@
         has_directives = true;
     }
     for (auto diagnostic : program_->AST().DiagnosticDirectives()) {
-        auto out = line();
+        auto out = Line();
         EmitDiagnosticControl(out, diagnostic->control);
         out << ";";
         has_directives = true;
     }
     if (has_directives) {
-        line();
+        Line();
     }
     // Generate global declarations in the order they appear in the module.
     for (auto* decl : program_->AST().GlobalDeclarations()) {
@@ -71,11 +71,11 @@
             decl,  //
             [&](const ast::TypeDecl* td) { return EmitTypeDecl(td); },
             [&](const ast::Function* func) { return EmitFunction(func); },
-            [&](const ast::Variable* var) { return EmitVariable(line(), var); },
+            [&](const ast::Variable* var) { return EmitVariable(Line(), var); },
             [&](const ast::ConstAssert* ca) { return EmitConstAssert(ca); },
             [&](Default) { TINT_UNREACHABLE(Writer, diagnostics_); });
         if (decl != program_->AST().GlobalDeclarations().Back()) {
-            line();
+            Line();
         }
     }
 }
@@ -86,7 +86,7 @@
 }
 
 void GeneratorImpl::EmitEnable(const ast::Enable* enable) {
-    auto out = line();
+    auto out = Line();
     out << "enable ";
     for (auto* ext : enable->extensions) {
         if (ext != enable->extensions.Front()) {
@@ -101,7 +101,7 @@
     Switch(
         ty,  //
         [&](const ast::Alias* alias) {
-            auto out = line();
+            auto out = Line();
             out << "alias " << alias->name->symbol.Name() << " = ";
             EmitExpression(out, alias->type);
             out << ";";
@@ -233,10 +233,10 @@
 
 void GeneratorImpl::EmitFunction(const ast::Function* func) {
     if (func->attributes.Length()) {
-        EmitAttributes(line(), func->attributes);
+        EmitAttributes(Line(), func->attributes);
     }
     {
-        auto out = line();
+        auto out = Line();
         out << "fn " << func->name->symbol.Name() << "(";
 
         bool first = true;
@@ -277,7 +277,7 @@
 
     if (func->body) {
         EmitStatementsWithIndent(func->body->statements);
-        line() << "}";
+        Line() << "}";
     }
 }
 
@@ -294,19 +294,19 @@
 
 void GeneratorImpl::EmitStructType(const ast::Struct* str) {
     if (str->attributes.Length()) {
-        EmitAttributes(line(), str->attributes);
+        EmitAttributes(Line(), str->attributes);
     }
-    line() << "struct " << str->name->symbol.Name() << " {";
+    Line() << "struct " << str->name->symbol.Name() << " {";
 
     auto add_padding = [&](uint32_t size) {
-        line() << "@size(" << size << ")";
+        Line() << "@size(" << size << ")";
 
         // Note: u32 is the smallest primitive we currently support. When WGSL
         // supports smaller types, this will need to be updated.
-        line() << UniqueIdentifier("padding") << " : u32,";
+        Line() << UniqueIdentifier("padding") << " : u32,";
     };
 
-    increment_indent();
+    IncrementIndent();
     uint32_t offset = 0;
     for (auto* mem : str->members) {
         // TODO(crbug.com/tint/798) move the @offset attribute handling to the transform::Wgsl
@@ -327,7 +327,7 @@
         attributes_sanitized.Reserve(mem->attributes.Length());
         for (auto* attr : mem->attributes) {
             if (attr->Is<ast::StructMemberOffsetAttribute>()) {
-                auto l = line();
+                auto l = Line();
                 l << "/* ";
                 EmitAttributes(l, utils::Vector{attr});
                 l << " */";
@@ -337,17 +337,17 @@
         }
 
         if (!attributes_sanitized.IsEmpty()) {
-            EmitAttributes(line(), attributes_sanitized);
+            EmitAttributes(Line(), attributes_sanitized);
         }
 
-        auto out = line();
+        auto out = Line();
         out << mem->name->symbol.Name() << " : ";
         EmitExpression(out, mem->type);
         out << ",";
     }
-    decrement_indent();
+    DecrementIndent();
 
-    line() << "}";
+    Line() << "}";
 }
 
 void GeneratorImpl::EmitVariable(utils::StringStream& out, const ast::Variable* v) {
@@ -579,11 +579,11 @@
 
 void GeneratorImpl::EmitBlock(const ast::BlockStatement* stmt) {
     {
-        auto out = line();
+        auto out = Line();
         EmitBlockHeader(out, stmt);
     }
     EmitStatementsWithIndent(stmt->statements);
-    line() << "}";
+    Line() << "}";
 }
 
 void GeneratorImpl::EmitBlockHeader(utils::StringStream& out, const ast::BlockStatement* stmt) {
@@ -602,7 +602,7 @@
         [&](const ast::BreakStatement* b) { EmitBreak(b); },
         [&](const ast::BreakIfStatement* b) { EmitBreakIf(b); },
         [&](const ast::CallStatement* c) {
-            auto out = line();
+            auto out = Line();
             EmitCall(out, c->expr);
             out << ";";
         },
@@ -617,7 +617,7 @@
         [&](const ast::ReturnStatement* r) { EmitReturn(r); },
         [&](const ast::ConstAssert* c) { EmitConstAssert(c); },
         [&](const ast::SwitchStatement* s) { EmitSwitch(s); },
-        [&](const ast::VariableDeclStatement* v) { EmitVariable(line(), v->variable); },
+        [&](const ast::VariableDeclStatement* v) { EmitVariable(Line(), v->variable); },
         [&](Default) {
             diagnostics_.add_error(diag::System::Writer,
                                    "unknown statement type: " + std::string(stmt->TypeInfo().name));
@@ -636,7 +636,7 @@
 }
 
 void GeneratorImpl::EmitAssign(const ast::AssignmentStatement* stmt) {
-    auto out = line();
+    auto out = Line();
 
     EmitExpression(out, stmt->lhs);
     out << " = ";
@@ -645,11 +645,11 @@
 }
 
 void GeneratorImpl::EmitBreak(const ast::BreakStatement*) {
-    line() << "break;";
+    Line() << "break;";
 }
 
 void GeneratorImpl::EmitBreakIf(const ast::BreakIfStatement* b) {
-    auto out = line();
+    auto out = Line();
 
     out << "break if ";
     EmitExpression(out, b->condition);
@@ -658,11 +658,11 @@
 
 void GeneratorImpl::EmitCase(const ast::CaseStatement* stmt) {
     if (stmt->selectors.Length() == 1 && stmt->ContainsDefault()) {
-        auto out = line();
+        auto out = Line();
         out << "default: ";
         EmitBlockHeader(out, stmt->body);
     } else {
-        auto out = line();
+        auto out = Line();
         out << "case ";
 
         bool first = true;
@@ -683,11 +683,11 @@
         EmitBlockHeader(out, stmt->body);
     }
     EmitStatementsWithIndent(stmt->body->statements);
-    line() << "}";
+    Line() << "}";
 }
 
 void GeneratorImpl::EmitCompoundAssign(const ast::CompoundAssignmentStatement* stmt) {
-    auto out = line();
+    auto out = Line();
 
     EmitExpression(out, stmt->lhs);
     out << " ";
@@ -698,12 +698,12 @@
 }
 
 void GeneratorImpl::EmitContinue(const ast::ContinueStatement*) {
-    line() << "continue;";
+    Line() << "continue;";
 }
 
 void GeneratorImpl::EmitIf(const ast::IfStatement* stmt) {
     {
-        auto out = line();
+        auto out = Line();
 
         if (!stmt->attributes.IsEmpty()) {
             EmitAttributes(out, stmt->attributes);
@@ -722,7 +722,7 @@
     while (e) {
         if (auto* elseif = e->As<ast::IfStatement>()) {
             {
-                auto out = line();
+                auto out = Line();
                 out << "} else if (";
                 EmitExpression(out, elseif->condition);
                 out << ") ";
@@ -733,7 +733,7 @@
         } else {
             auto* body = e->As<ast::BlockStatement>();
             {
-                auto out = line();
+                auto out = Line();
                 out << "} else ";
                 EmitBlockHeader(out, body);
             }
@@ -742,22 +742,22 @@
         }
     }
 
-    line() << "}";
+    Line() << "}";
 }
 
 void GeneratorImpl::EmitIncrementDecrement(const ast::IncrementDecrementStatement* stmt) {
-    auto out = line();
+    auto out = Line();
     EmitExpression(out, stmt->lhs);
     out << (stmt->increment ? "++" : "--") << ";";
 }
 
 void GeneratorImpl::EmitDiscard(const ast::DiscardStatement*) {
-    line() << "discard;";
+    Line() << "discard;";
 }
 
 void GeneratorImpl::EmitLoop(const ast::LoopStatement* stmt) {
     {
-        auto out = line();
+        auto out = Line();
 
         if (!stmt->attributes.IsEmpty()) {
             EmitAttributes(out, stmt->attributes);
@@ -767,14 +767,14 @@
         out << "loop ";
         EmitBlockHeader(out, stmt->body);
     }
-    increment_indent();
+    IncrementIndent();
 
     EmitStatements(stmt->body->statements);
 
     if (stmt->continuing && !stmt->continuing->Empty()) {
-        line();
+        Line();
         {
-            auto out = line();
+            auto out = Line();
             out << "continuing ";
             if (!stmt->continuing->attributes.IsEmpty()) {
                 EmitAttributes(out, stmt->continuing->attributes);
@@ -783,11 +783,11 @@
             out << "{";
         }
         EmitStatementsWithIndent(stmt->continuing->statements);
-        line() << "}";
+        Line() << "}";
     }
 
-    decrement_indent();
-    line() << "}";
+    DecrementIndent();
+    Line() << "}";
 }
 
 void GeneratorImpl::EmitForLoop(const ast::ForLoopStatement* stmt) {
@@ -804,7 +804,7 @@
     }
 
     {
-        auto out = line();
+        auto out = Line();
 
         if (!stmt->attributes.IsEmpty()) {
             EmitAttributes(out, stmt->attributes);
@@ -858,12 +858,12 @@
 
     EmitStatementsWithIndent(stmt->body->statements);
 
-    line() << "}";
+    Line() << "}";
 }
 
 void GeneratorImpl::EmitWhile(const ast::WhileStatement* stmt) {
     {
-        auto out = line();
+        auto out = Line();
 
         if (!stmt->attributes.IsEmpty()) {
             EmitAttributes(out, stmt->attributes);
@@ -883,11 +883,11 @@
 
     EmitStatementsWithIndent(stmt->body->statements);
 
-    line() << "}";
+    Line() << "}";
 }
 
 void GeneratorImpl::EmitReturn(const ast::ReturnStatement* stmt) {
-    auto out = line();
+    auto out = Line();
 
     out << "return";
     if (stmt->value) {
@@ -898,7 +898,7 @@
 }
 
 void GeneratorImpl::EmitConstAssert(const ast::ConstAssert* stmt) {
-    auto out = line();
+    auto out = Line();
     out << "const_assert ";
     EmitExpression(out, stmt->condition);
     out << ";";
@@ -906,7 +906,7 @@
 
 void GeneratorImpl::EmitSwitch(const ast::SwitchStatement* stmt) {
     {
-        auto out = line();
+        auto out = Line();
 
         if (!stmt->attributes.IsEmpty()) {
             EmitAttributes(out, stmt->attributes);
@@ -932,7 +932,7 @@
         }
     }
 
-    line() << "}";
+    Line() << "}";
 }
 
 }  // namespace tint::writer::wgsl
diff --git a/src/tint/writer/wgsl/generator_impl.h b/src/tint/writer/wgsl/generator_impl.h
index 6c67d79..25df464 100644
--- a/src/tint/writer/wgsl/generator_impl.h
+++ b/src/tint/writer/wgsl/generator_impl.h
@@ -46,7 +46,7 @@
     /// Constructor
     /// @param program the program
     explicit GeneratorImpl(const Program* program);
-    ~GeneratorImpl();
+    ~GeneratorImpl() override;
 
     /// Generates the result data
     void Generate();
diff --git a/src/tint/writer/wgsl/generator_impl_alias_type_test.cc b/src/tint/writer/wgsl/generator_impl_alias_type_test.cc
index 9c76148..719c11c 100644
--- a/src/tint/writer/wgsl/generator_impl_alias_type_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_alias_type_test.cc
@@ -28,7 +28,7 @@
     gen.EmitTypeDecl(alias);
 
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(alias a = f32;
+    EXPECT_EQ(gen.Result(), R"(alias a = f32;
 )");
 }
 
@@ -46,7 +46,7 @@
 
     gen.EmitTypeDecl(alias);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(struct A {
+    EXPECT_EQ(gen.Result(), R"(struct A {
   a : f32,
   b : i32,
 }
@@ -66,7 +66,7 @@
 
     gen.EmitTypeDecl(alias);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(alias B = A;
+    EXPECT_EQ(gen.Result(), R"(alias B = A;
 )");
 }
 
diff --git a/src/tint/writer/wgsl/generator_impl_assign_test.cc b/src/tint/writer/wgsl/generator_impl_assign_test.cc
index 5d7ab23..390da01 100644
--- a/src/tint/writer/wgsl/generator_impl_assign_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_assign_test.cc
@@ -29,11 +29,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(assign);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), "  lhs = rhs;\n");
+    EXPECT_EQ(gen.Result(), "  lhs = rhs;\n");
 }
 
 }  // namespace
diff --git a/src/tint/writer/wgsl/generator_impl_block_test.cc b/src/tint/writer/wgsl/generator_impl_block_test.cc
index d5af303..daaf47b 100644
--- a/src/tint/writer/wgsl/generator_impl_block_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_block_test.cc
@@ -27,11 +27,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(b);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  {
+    EXPECT_EQ(gen.Result(), R"(  {
     return;
   }
 )");
diff --git a/src/tint/writer/wgsl/generator_impl_break_test.cc b/src/tint/writer/wgsl/generator_impl_break_test.cc
index d60cef4..4adf057 100644
--- a/src/tint/writer/wgsl/generator_impl_break_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_break_test.cc
@@ -27,11 +27,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(b);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), "  break;\n");
+    EXPECT_EQ(gen.Result(), "  break;\n");
 }
 
 }  // namespace
diff --git a/src/tint/writer/wgsl/generator_impl_call_test.cc b/src/tint/writer/wgsl/generator_impl_call_test.cc
index 5cb8eac..a6ca7df 100644
--- a/src/tint/writer/wgsl/generator_impl_call_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_call_test.cc
@@ -82,10 +82,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(stmt);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), "  my_func(param1, param2);\n");
+    EXPECT_EQ(gen.Result(), "  my_func(param1, param2);\n");
 }
 
 }  // namespace
diff --git a/src/tint/writer/wgsl/generator_impl_case_test.cc b/src/tint/writer/wgsl/generator_impl_case_test.cc
index 05b0d9e..8664ea3 100644
--- a/src/tint/writer/wgsl/generator_impl_case_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_case_test.cc
@@ -30,11 +30,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitCase(s->body[0]);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  case 5i: {
+    EXPECT_EQ(gen.Result(), R"(  case 5i: {
     break;
   }
 )");
@@ -53,11 +53,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitCase(s->body[0]);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  case 5i, 6i: {
+    EXPECT_EQ(gen.Result(), R"(  case 5i, 6i: {
     break;
   }
 )");
@@ -69,11 +69,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitCase(s->body[0]);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  default: {
+    EXPECT_EQ(gen.Result(), R"(  default: {
     break;
   }
 )");
diff --git a/src/tint/writer/wgsl/generator_impl_const_assert_test.cc b/src/tint/writer/wgsl/generator_impl_const_assert_test.cc
index d3f22ef..260ce68 100644
--- a/src/tint/writer/wgsl/generator_impl_const_assert_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_const_assert_test.cc
@@ -29,7 +29,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(const_assert true;
+    EXPECT_EQ(gen.Result(), R"(const_assert true;
 )");
 }
 
@@ -39,7 +39,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(fn f() {
+    EXPECT_EQ(gen.Result(), R"(fn f() {
   const_assert true;
 }
 )");
diff --git a/src/tint/writer/wgsl/generator_impl_constructor_test.cc b/src/tint/writer/wgsl/generator_impl_constructor_test.cc
index e360be2..99c5364 100644
--- a/src/tint/writer/wgsl/generator_impl_constructor_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_constructor_test.cc
@@ -32,7 +32,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("false"));
+    EXPECT_THAT(gen.Result(), HasSubstr("false"));
 }
 
 TEST_F(WgslGeneratorImplTest_Constructor, Int) {
@@ -41,7 +41,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("-12345"));
+    EXPECT_THAT(gen.Result(), HasSubstr("-12345"));
 }
 
 TEST_F(WgslGeneratorImplTest_Constructor, UInt) {
@@ -50,7 +50,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("56779u"));
+    EXPECT_THAT(gen.Result(), HasSubstr("56779u"));
 }
 
 TEST_F(WgslGeneratorImplTest_Constructor, F32) {
@@ -61,7 +61,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("1073741824.0f"));
+    EXPECT_THAT(gen.Result(), HasSubstr("1073741824.0f"));
 }
 
 TEST_F(WgslGeneratorImplTest_Constructor, F16) {
@@ -74,7 +74,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("32752.0h"));
+    EXPECT_THAT(gen.Result(), HasSubstr("32752.0h"));
 }
 
 TEST_F(WgslGeneratorImplTest_Constructor, Type_F32) {
@@ -84,7 +84,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("f32(-0.00001200000042445026f)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("f32(-0.00001200000042445026f)"));
 }
 
 TEST_F(WgslGeneratorImplTest_Constructor, Type_F16) {
@@ -96,7 +96,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("f16(-0.00001198053359985352h)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("f16(-0.00001198053359985352h)"));
 }
 
 TEST_F(WgslGeneratorImplTest_Constructor, Type_Bool) {
@@ -106,7 +106,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("bool(true)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("bool(true)"));
 }
 
 TEST_F(WgslGeneratorImplTest_Constructor, Type_Int) {
@@ -116,7 +116,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("i32(-12345i)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("i32(-12345i)"));
 }
 
 TEST_F(WgslGeneratorImplTest_Constructor, Type_Uint) {
@@ -126,7 +126,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("u32(12345u)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("u32(12345u)"));
 }
 
 TEST_F(WgslGeneratorImplTest_Constructor, Type_Vec_F32) {
@@ -136,7 +136,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("vec3<f32>(1.0f, 2.0f, 3.0f)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("vec3<f32>(1.0f, 2.0f, 3.0f)"));
 }
 
 TEST_F(WgslGeneratorImplTest_Constructor, Type_Vec_F16) {
@@ -148,7 +148,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("vec3<f16>(1.0h, 2.0h, 3.0h)"));
+    EXPECT_THAT(gen.Result(), HasSubstr("vec3<f16>(1.0h, 2.0h, 3.0h)"));
 }
 
 TEST_F(WgslGeneratorImplTest_Constructor, Type_Mat_F32) {
@@ -159,7 +159,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("mat2x3<f32>(vec3<f32>(1.0f, 2.0f, 3.0f), "
+    EXPECT_THAT(gen.Result(), HasSubstr("mat2x3<f32>(vec3<f32>(1.0f, 2.0f, 3.0f), "
                                         "vec3<f32>(3.0f, 4.0f, 5.0f))"));
 }
 
@@ -173,7 +173,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(), HasSubstr("mat2x3<f16>(vec3<f16>(1.0h, 2.0h, 3.0h), "
+    EXPECT_THAT(gen.Result(), HasSubstr("mat2x3<f16>(vec3<f16>(1.0h, 2.0h, 3.0h), "
                                         "vec3<f16>(3.0h, 4.0h, 5.0h))"));
 }
 
@@ -185,7 +185,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(),
+    EXPECT_THAT(gen.Result(),
                 HasSubstr("array<vec3<f32>, 3u>(vec3<f32>(1.0f, 2.0f, 3.0f), "
                           "vec3<f32>(4.0f, 5.0f, 6.0f), vec3<f32>(7.0f, 8.0f, 9.0f))"));
 }
@@ -198,7 +198,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_THAT(gen.result(),
+    EXPECT_THAT(gen.Result(),
                 HasSubstr("array(vec3<f32>(1.0f, 2.0f, 3.0f), "
                           "vec3<f32>(4.0f, 5.0f, 6.0f), vec3<f32>(7.0f, 8.0f, 9.0f))"));
 }
diff --git a/src/tint/writer/wgsl/generator_impl_continue_test.cc b/src/tint/writer/wgsl/generator_impl_continue_test.cc
index e1b9056..003e5ad 100644
--- a/src/tint/writer/wgsl/generator_impl_continue_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_continue_test.cc
@@ -29,11 +29,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(c);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), "  continue;\n");
+    EXPECT_EQ(gen.Result(), "  continue;\n");
 }
 
 }  // namespace
diff --git a/src/tint/writer/wgsl/generator_impl_diagnostic_test.cc b/src/tint/writer/wgsl/generator_impl_diagnostic_test.cc
index 2aeab09..2e40cd1 100644
--- a/src/tint/writer/wgsl/generator_impl_diagnostic_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_diagnostic_test.cc
@@ -27,7 +27,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(diagnostic(error, chromium.unreachable_code);
+    EXPECT_EQ(gen.Result(), R"(diagnostic(error, chromium.unreachable_code);
 
 )");
 }
@@ -40,7 +40,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(@diagnostic(error, chromium.unreachable_code)
+    EXPECT_EQ(gen.Result(), R"(@diagnostic(error, chromium.unreachable_code)
 fn foo() {
 }
 )");
diff --git a/src/tint/writer/wgsl/generator_impl_discard_test.cc b/src/tint/writer/wgsl/generator_impl_discard_test.cc
index 4a5ae25..06f5a90 100644
--- a/src/tint/writer/wgsl/generator_impl_discard_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_discard_test.cc
@@ -29,11 +29,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(stmt);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), "  discard;\n");
+    EXPECT_EQ(gen.Result(), "  discard;\n");
 }
 
 }  // namespace
diff --git a/src/tint/writer/wgsl/generator_impl_enable_test.cc b/src/tint/writer/wgsl/generator_impl_enable_test.cc
index 34d1614..8bf208b 100644
--- a/src/tint/writer/wgsl/generator_impl_enable_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_enable_test.cc
@@ -28,7 +28,7 @@
 
     gen.EmitEnable(enable);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(enable f16;
+    EXPECT_EQ(gen.Result(), R"(enable f16;
 )");
 }
 
diff --git a/src/tint/writer/wgsl/generator_impl_function_test.cc b/src/tint/writer/wgsl/generator_impl_function_test.cc
index 14de0c2..d39fd0b 100644
--- a/src/tint/writer/wgsl/generator_impl_function_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_function_test.cc
@@ -35,10 +35,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitFunction(func);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  fn my_func() {
+    EXPECT_EQ(gen.Result(), R"(  fn my_func() {
     return;
   }
 )");
@@ -57,10 +57,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitFunction(func);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  fn my_func(a : f32, b : i32) {
+    EXPECT_EQ(gen.Result(), R"(  fn my_func(a : f32, b : i32) {
     return;
   }
 )");
@@ -78,10 +78,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitFunction(func);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  @compute @workgroup_size(2i, 4i, 6i)
+    EXPECT_EQ(gen.Result(), R"(  @compute @workgroup_size(2i, 4i, 6i)
   fn my_func() {
     return;
   }
@@ -99,10 +99,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitFunction(func);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  @must_use
+    EXPECT_EQ(gen.Result(), R"(  @must_use
   fn my_func() -> i32 {
     return 1i;
   }
@@ -122,10 +122,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitFunction(func);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  @compute @workgroup_size(2i, height)
+    EXPECT_EQ(gen.Result(), R"(  @compute @workgroup_size(2i, height)
   fn my_func() {
     return;
   }
@@ -149,10 +149,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitFunction(func);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  @fragment
+    EXPECT_EQ(gen.Result(), R"(  @fragment
   fn frag_main(@builtin(position) coord : vec4<f32>, @location(1) loc1 : f32) {
   }
 )");
@@ -172,10 +172,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitFunction(func);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  @fragment
+    EXPECT_EQ(gen.Result(), R"(  @fragment
   fn frag_main() -> @location(1) f32 {
     return 1.0f;
   }
@@ -238,7 +238,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(struct Data {
+    EXPECT_EQ(gen.Result(), R"(struct Data {
   d : f32,
 }
 
diff --git a/src/tint/writer/wgsl/generator_impl_global_decl_test.cc b/src/tint/writer/wgsl/generator_impl_global_decl_test.cc
index 9d97f85..0734f6a 100644
--- a/src/tint/writer/wgsl/generator_impl_global_decl_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_global_decl_test.cc
@@ -35,10 +35,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  @compute @workgroup_size(1i, 1i, 1i)
+    EXPECT_EQ(gen.Result(), R"(  @compute @workgroup_size(1i, 1i, 1i)
   fn test_function() {
     var a : f32;
   }
@@ -79,10 +79,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  var<private> a0 : f32;
+    EXPECT_EQ(gen.Result(), R"(  var<private> a0 : f32;
 
   struct S0 {
     a : i32,
@@ -112,10 +112,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), "  @group(0) @binding(0) var s : sampler;\n");
+    EXPECT_EQ(gen.Result(), "  @group(0) @binding(0) var s : sampler;\n");
 }
 
 TEST_F(WgslGeneratorImplTest, Emit_Global_Texture) {
@@ -124,10 +124,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), "  @group(0) @binding(0) var t : texture_1d<f32>;\n");
+    EXPECT_EQ(gen.Result(), "  @group(0) @binding(0) var t : texture_1d<f32>;\n");
 }
 
 TEST_F(WgslGeneratorImplTest, Emit_GlobalConst) {
@@ -136,10 +136,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  const explicit : f32 = 1.0f;
+    EXPECT_EQ(gen.Result(), R"(  const explicit : f32 = 1.0f;
 
   const inferred = 1.0f;
 )");
@@ -151,10 +151,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  override a : f32;
+    EXPECT_EQ(gen.Result(), R"(  override a : f32;
 
   @id(7) override b : f32;
 )");
diff --git a/src/tint/writer/wgsl/generator_impl_if_test.cc b/src/tint/writer/wgsl/generator_impl_if_test.cc
index 968b03a..962ea02 100644
--- a/src/tint/writer/wgsl/generator_impl_if_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_if_test.cc
@@ -31,11 +31,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(i);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  if (cond) {
+    EXPECT_EQ(gen.Result(), R"(  if (cond) {
     return;
   }
 )");
@@ -55,11 +55,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(i);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  if (cond) {
+    EXPECT_EQ(gen.Result(), R"(  if (cond) {
     return;
   } else if (else_cond) {
     return;
@@ -79,11 +79,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(i);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  if (cond) {
+    EXPECT_EQ(gen.Result(), R"(  if (cond) {
     return;
   } else {
     return;
@@ -108,11 +108,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(i);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  if (cond) {
+    EXPECT_EQ(gen.Result(), R"(  if (cond) {
     return;
   } else if (else_cond) {
     return;
diff --git a/src/tint/writer/wgsl/generator_impl_loop_test.cc b/src/tint/writer/wgsl/generator_impl_loop_test.cc
index 58b4ea8..48b0244 100644
--- a/src/tint/writer/wgsl/generator_impl_loop_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_loop_test.cc
@@ -33,11 +33,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(l);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  loop {
+    EXPECT_EQ(gen.Result(), R"(  loop {
     break;
   }
 )");
@@ -55,11 +55,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(l);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  loop {
+    EXPECT_EQ(gen.Result(), R"(  loop {
     break;
 
     continuing {
@@ -81,11 +81,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(l);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  loop {
+    EXPECT_EQ(gen.Result(), R"(  loop {
     discard;
 
     continuing {
@@ -108,11 +108,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(f);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  for({
+    EXPECT_EQ(gen.Result(), R"(  for({
     _ = 1i;
     _ = 2i;
   }; ; ) {
@@ -131,11 +131,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(f);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  for(; true; ) {
+    EXPECT_EQ(gen.Result(), R"(  for(; true; ) {
     return;
   }
 )");
@@ -152,11 +152,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(f);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  for(; ; i = (i + 1i)) {
+    EXPECT_EQ(gen.Result(), R"(  for(; ; i = (i + 1i)) {
     return;
   }
 )");
@@ -175,11 +175,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(f);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  for(; ; {
+    EXPECT_EQ(gen.Result(), R"(  for(; ; {
     _ = 1i;
     _ = 2i;
   }) {
@@ -198,11 +198,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(f);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  for(var i : i32; true; i = (i + 1i)) {
+    EXPECT_EQ(gen.Result(), R"(  for(var i : i32; true; i = (i + 1i)) {
     return;
   }
 )");
@@ -221,11 +221,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(f);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  for({
+    EXPECT_EQ(gen.Result(), R"(  for({
     _ = 1i;
     _ = 2i;
   }; true; {
@@ -247,11 +247,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(f);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  while(true) {
+    EXPECT_EQ(gen.Result(), R"(  while(true) {
     return;
   }
 )");
@@ -267,11 +267,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(f);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  while(true) {
+    EXPECT_EQ(gen.Result(), R"(  while(true) {
     continue;
   }
 )");
@@ -289,11 +289,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(f);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  while((true && false)) {
+    EXPECT_EQ(gen.Result(), R"(  while((true && false)) {
     return;
   }
 )");
diff --git a/src/tint/writer/wgsl/generator_impl_return_test.cc b/src/tint/writer/wgsl/generator_impl_return_test.cc
index 631dbaf..626dc55 100644
--- a/src/tint/writer/wgsl/generator_impl_return_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_return_test.cc
@@ -29,11 +29,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(r);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), "  return;\n");
+    EXPECT_EQ(gen.Result(), "  return;\n");
 }
 
 TEST_F(WgslGeneratorImplTest, Emit_ReturnWithValue) {
@@ -42,11 +42,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(r);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), "  return 123i;\n");
+    EXPECT_EQ(gen.Result(), "  return 123i;\n");
 }
 
 }  // namespace
diff --git a/src/tint/writer/wgsl/generator_impl_switch_test.cc b/src/tint/writer/wgsl/generator_impl_switch_test.cc
index 7ec5584..e913710 100644
--- a/src/tint/writer/wgsl/generator_impl_switch_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_switch_test.cc
@@ -43,11 +43,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(s);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  switch(cond) {
+    EXPECT_EQ(gen.Result(), R"(  switch(cond) {
     case 5i: {
       break;
     }
@@ -70,10 +70,10 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
     gen.EmitStatement(s);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(  switch(cond) {
+    EXPECT_EQ(gen.Result(), R"(  switch(cond) {
     case 5i, default: {
       break;
     }
diff --git a/src/tint/writer/wgsl/generator_impl_test.cc b/src/tint/writer/wgsl/generator_impl_test.cc
index b58c0be..dc4b0e9 100644
--- a/src/tint/writer/wgsl/generator_impl_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_test.cc
@@ -29,7 +29,7 @@
 
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(fn my_func() {
+    EXPECT_EQ(gen.Result(), R"(fn my_func() {
 }
 )");
 }
diff --git a/src/tint/writer/wgsl/generator_impl_type_test.cc b/src/tint/writer/wgsl/generator_impl_type_test.cc
index 22d7bf0..a7679dc 100644
--- a/src/tint/writer/wgsl/generator_impl_type_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_type_test.cc
@@ -193,7 +193,7 @@
 
     gen.EmitStructType(s);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(struct S {
+    EXPECT_EQ(gen.Result(), R"(struct S {
   @size(8)
   padding : u32,
   /* @offset(8) */
@@ -217,7 +217,7 @@
 
     gen.EmitStructType(s);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(struct S {
+    EXPECT_EQ(gen.Result(), R"(struct S {
   @size(8)
   padding : u32,
   /* @offset(8) */
@@ -240,7 +240,7 @@
 
     gen.EmitStructType(s);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(struct S {
+    EXPECT_EQ(gen.Result(), R"(struct S {
   @align(8)
   a : i32,
   @align(16)
@@ -259,7 +259,7 @@
 
     gen.EmitStructType(s);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(struct S {
+    EXPECT_EQ(gen.Result(), R"(struct S {
   @size(16)
   a : i32,
   @size(32)
@@ -278,7 +278,7 @@
 
     gen.EmitStructType(s);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(struct S {
+    EXPECT_EQ(gen.Result(), R"(struct S {
   a : i32,
   @align(8)
   b : f32,
@@ -297,7 +297,7 @@
 
     gen.EmitStructType(s);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(struct S {
+    EXPECT_EQ(gen.Result(), R"(struct S {
   @builtin(vertex_index)
   a : u32,
   @location(2)
diff --git a/src/tint/writer/wgsl/generator_impl_variable_decl_statement_test.cc b/src/tint/writer/wgsl/generator_impl_variable_decl_statement_test.cc
index f4c271b..325eb3d 100644
--- a/src/tint/writer/wgsl/generator_impl_variable_decl_statement_test.cc
+++ b/src/tint/writer/wgsl/generator_impl_variable_decl_statement_test.cc
@@ -33,11 +33,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(stmt);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), "  var a : f32;\n");
+    EXPECT_EQ(gen.Result(), "  var a : f32;\n");
 }
 
 TEST_F(WgslGeneratorImplTest, Emit_VariableDeclStatement_InferredType) {
@@ -48,11 +48,11 @@
 
     GeneratorImpl& gen = Build();
 
-    gen.increment_indent();
+    gen.IncrementIndent();
 
     gen.EmitStatement(stmt);
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), "  var a = 123i;\n");
+    EXPECT_EQ(gen.Result(), "  var a = 123i;\n");
 }
 
 TEST_F(WgslGeneratorImplTest, Emit_VariableDeclStatement_Const_AInt) {
@@ -66,7 +66,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(fn f() {
+    EXPECT_EQ(gen.Result(), R"(fn f() {
   const C = 1;
   let l = C;
 }
@@ -84,7 +84,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(fn f() {
+    EXPECT_EQ(gen.Result(), R"(fn f() {
   const C = 1.0;
   let l = C;
 }
@@ -102,7 +102,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(fn f() {
+    EXPECT_EQ(gen.Result(), R"(fn f() {
   const C = 1i;
   let l = C;
 }
@@ -120,7 +120,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(fn f() {
+    EXPECT_EQ(gen.Result(), R"(fn f() {
   const C = 1u;
   let l = C;
 }
@@ -138,7 +138,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(fn f() {
+    EXPECT_EQ(gen.Result(), R"(fn f() {
   const C = 1.0f;
   let l = C;
 }
@@ -158,7 +158,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(enable f16;
+    EXPECT_EQ(gen.Result(), R"(enable f16;
 
 fn f() {
   const C = 1.0h;
@@ -178,7 +178,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(fn f() {
+    EXPECT_EQ(gen.Result(), R"(fn f() {
   const C = vec3(1, 2, 3);
   let l = C;
 }
@@ -196,7 +196,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(fn f() {
+    EXPECT_EQ(gen.Result(), R"(fn f() {
   const C = vec3(1.0, 2.0, 3.0);
   let l = C;
 }
@@ -214,7 +214,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(fn f() {
+    EXPECT_EQ(gen.Result(), R"(fn f() {
   const C = vec3<f32>(1.0f, 2.0f, 3.0f);
   let l = C;
 }
@@ -234,7 +234,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(enable f16;
+    EXPECT_EQ(gen.Result(), R"(enable f16;
 
 fn f() {
   const C = vec3<f16>(1.0h, 2.0h, 3.0h);
@@ -254,7 +254,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(fn f() {
+    EXPECT_EQ(gen.Result(), R"(fn f() {
   const C = mat2x3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0);
   let l = C;
 }
@@ -272,7 +272,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(fn f() {
+    EXPECT_EQ(gen.Result(), R"(fn f() {
   const C = mat2x3<f32>(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f);
   let l = C;
 }
@@ -292,7 +292,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(enable f16;
+    EXPECT_EQ(gen.Result(), R"(enable f16;
 
 fn f() {
   const C = mat2x3<f16>(1.0h, 2.0h, 3.0h, 4.0h, 5.0h, 6.0h);
@@ -312,7 +312,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(fn f() {
+    EXPECT_EQ(gen.Result(), R"(fn f() {
   const C = array<f32, 3u>(1.0f, 2.0f, 3.0f);
   let l = C;
 }
@@ -333,7 +333,7 @@
     GeneratorImpl& gen = Build();
     gen.Generate();
     EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.result(), R"(fn f() {
+    EXPECT_EQ(gen.Result(), R"(fn f() {
   const C = array<vec2<bool>, 3u>(vec2<bool>(true, false), vec2<bool>(false, true), vec2<bool>(true, true));
   let l = C;
 }