[tint] Shuffle to break last circular dependencies

Change-Id: Id2a9d6292e26c54ff6603e4c053ebdacc898c4f9
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/143803
Reviewed-by: dan sinclair <dsinclair@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/include/tint/binding_point.h b/include/tint/binding_point.h
index 11c47d5..e23a5aa 100644
--- a/include/tint/binding_point.h
+++ b/include/tint/binding_point.h
@@ -22,6 +22,7 @@
 #include "src/tint/utils/math/hash.h"
 #include "src/tint/utils/reflection/reflection.h"
 #include "src/tint/utils/text/string_stream.h"
+#include "src/tint/utils/traits/traits.h"
 
 namespace tint {
 
diff --git a/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc b/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
index 18e06d6..3a1a367 100644
--- a/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
@@ -2951,6 +2951,15 @@
     }
 }
 
+std::string ASTPrinter::StructName(const type::Struct* s) {
+    auto name = s->Name().Name();
+    if (HasPrefix(name, "__")) {
+        name = tint::GetOrCreate(builtin_struct_names_, s,
+                                 [&] { return UniqueIdentifier(name.substr(2)); });
+    }
+    return name;
+}
+
 std::string ASTPrinter::UniqueIdentifier(const std::string& prefix /* = "" */) {
     return builder_.Symbols().New(prefix).Name();
 }
diff --git a/src/tint/lang/glsl/writer/ast_printer/ast_printer.h b/src/tint/lang/glsl/writer/ast_printer/ast_printer.h
index d6c7b79..d670dcf 100644
--- a/src/tint/lang/glsl/writer/ast_printer/ast_printer.h
+++ b/src/tint/lang/glsl/writer/ast_printer/ast_printer.h
@@ -439,8 +439,16 @@
     /// @returns the corresponding uint type
     type::Type* BoolTypeToUint(const type::Type* type);
 
-    /// @copydoc tint::TextWrtiter::UniqueIdentifier
-    std::string UniqueIdentifier(const std::string& prefix = "") override;
+    /// @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);
+
+    /// @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 = "");
 
     /// Alias for builder_.TypeOf(ptr)
     template <typename T>
@@ -449,7 +457,12 @@
     }
 
     ProgramBuilder builder_;
-    TextBuffer helpers_;  // Helper functions emitted at the top of the output
+
+    /// Helper functions emitted at the top of the output
+    TextBuffer helpers_;
+
+    /// Map of builtin structure to unique generated name
+    std::unordered_map<const type::Struct*, std::string> builtin_struct_names_;
     std::function<void()> emit_continuing_;
     std::unordered_map<const sem::Builtin*, std::string> builtins_;
     std::unordered_map<const type::Vector*, std::string> dynamic_vector_write_;
diff --git a/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc b/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc
index fa45bc8..98b7104 100644
--- a/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc
@@ -4589,6 +4589,15 @@
     return true;
 }
 
+std::string ASTPrinter::StructName(const type::Struct* s) {
+    auto name = s->Name().Name();
+    if (HasPrefix(name, "__")) {
+        name = tint::GetOrCreate(builtin_struct_names_, s,
+                                 [&] { return UniqueIdentifier(name.substr(2)); });
+    }
+    return name;
+}
+
 std::string ASTPrinter::UniqueIdentifier(const std::string& prefix /* = "" */) {
     return builder_.Symbols().New(prefix).Name();
 }
diff --git a/src/tint/lang/hlsl/writer/ast_printer/ast_printer.h b/src/tint/lang/hlsl/writer/ast_printer/ast_printer.h
index 1e586dc..8281290 100644
--- a/src/tint/lang/hlsl/writer/ast_printer/ast_printer.h
+++ b/src/tint/lang/hlsl/writer/ast_printer/ast_printer.h
@@ -548,8 +548,16 @@
                            const sem::Builtin* builtin,
                            F&& build);
 
-    /// @copydoc tint::TextWrtiter::UniqueIdentifier
-    std::string UniqueIdentifier(const std::string& prefix = "") override;
+    /// @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);
+
+    /// @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 = "");
 
     /// Alias for builder_.TypeOf(ptr)
     template <typename T>
@@ -558,7 +566,12 @@
     }
 
     ProgramBuilder builder_;
-    TextBuffer helpers_;  // Helper functions emitted at the top of the output
+
+    /// Helper functions emitted at the top of the output
+    TextBuffer helpers_;
+
+    /// Map of builtin structure to unique generated name
+    std::unordered_map<const type::Struct*, std::string> builtin_struct_names_;
     std::function<bool()> emit_continuing_;
     std::unordered_map<const type::Matrix*, std::string> matrix_scalar_inits_;
     std::unordered_map<const sem::Builtin*, std::string> builtins_;
diff --git a/src/tint/lang/msl/writer/ast_printer/ast_printer.cc b/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
index ddf450f..80155eb 100644
--- a/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
@@ -3033,6 +3033,15 @@
     return array_template_name_;
 }
 
+std::string ASTPrinter::StructName(const type::Struct* s) {
+    auto name = s->Name().Name();
+    if (HasPrefix(name, "__")) {
+        name = tint::GetOrCreate(builtin_struct_names_, s,
+                                 [&] { return UniqueIdentifier(name.substr(2)); });
+    }
+    return name;
+}
+
 std::string ASTPrinter::UniqueIdentifier(const std::string& prefix /* = "" */) {
     return builder_.Symbols().New(prefix).Name();
 }
diff --git a/src/tint/lang/msl/writer/ast_printer/ast_printer.h b/src/tint/lang/msl/writer/ast_printer/ast_printer.h
index 32d23ab..5086616 100644
--- a/src/tint/lang/msl/writer/ast_printer/ast_printer.h
+++ b/src/tint/lang/msl/writer/ast_printer/ast_printer.h
@@ -378,8 +378,16 @@
     /// first call.
     const std::string& ArrayType();
 
-    /// @copydoc tint::TextWrtiter::UniqueIdentifier
-    std::string UniqueIdentifier(const std::string& prefix = "") override;
+    /// @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);
+
+    /// @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 = "");
 
     /// Alias for builder_.TypeOf(ptr)
     template <typename T>
@@ -391,6 +399,9 @@
 
     TextBuffer helpers_;  // Helper functions emitted at the top of the output
 
+    /// Map of builtin structure to unique generated name
+    std::unordered_map<const type::Struct*, std::string> builtin_struct_names_;
+
     std::function<bool()> emit_continuing_;
 
     /// Name of atomicCompareExchangeWeak() helper for the given pointer storage
diff --git a/src/tint/lang/msl/writer/printer/printer.cc b/src/tint/lang/msl/writer/printer/printer.cc
index a56c751..1b7f2a5 100644
--- a/src/tint/lang/msl/writer/printer/printer.cc
+++ b/src/tint/lang/msl/writer/printer/printer.cc
@@ -37,8 +37,10 @@
 #include "src/tint/lang/core/type/vector.h"
 #include "src/tint/lang/core/type/void.h"
 #include "src/tint/lang/msl/writer/common/printer_support.h"
+#include "src/tint/utils/containers/map.h"
 #include "src/tint/utils/macros/scoped_assignment.h"
 #include "src/tint/utils/rtti/switch.h"
+#include "src/tint/utils/text/string.h"
 
 namespace tint::msl::writer {
 namespace {
@@ -512,6 +514,15 @@
         [&](Default) { UNHANDLED_CASE(c->Type()); });
 }
 
+std::string Printer::StructName(const type::Struct* s) {
+    auto name = s->Name().Name();
+    if (HasPrefix(name, "__")) {
+        name = tint::GetOrCreate(builtin_struct_names_, s,
+                                 [&] { return UniqueIdentifier(name.substr(2)); });
+    }
+    return name;
+}
+
 std::string Printer::UniqueIdentifier(const std::string& prefix /* = "" */) {
     return ir_->symbols.New(prefix).Name();
 }
diff --git a/src/tint/lang/msl/writer/printer/printer.h b/src/tint/lang/msl/writer/printer/printer.h
index acc42d5..92f7ffd 100644
--- a/src/tint/lang/msl/writer/printer/printer.h
+++ b/src/tint/lang/msl/writer/printer/printer.h
@@ -16,6 +16,7 @@
 #define SRC_TINT_LANG_MSL_WRITER_PRINTER_PRINTER_H_
 
 #include <string>
+#include <unordered_map>
 #include <unordered_set>
 
 #include "src/tint/lang/core/ir/module.h"
@@ -100,8 +101,19 @@
     std::string array_template_name_;
 
   private:
-    /// @copydoc tint::TextWrtiter::UniqueIdentifier
-    std::string UniqueIdentifier(const std::string& prefix = "") override;
+    /// @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);
+
+    /// @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 = "");
+
+    /// Map of builtin structure to unique generated name
+    std::unordered_map<const type::Struct*, std::string> builtin_struct_names_;
 
     ir::Module* const ir_;
 
diff --git a/src/tint/utils/containers/scope_stack.h b/src/tint/utils/containers/scope_stack.h
index 03da975..d8e3784 100644
--- a/src/tint/utils/containers/scope_stack.h
+++ b/src/tint/utils/containers/scope_stack.h
@@ -18,7 +18,6 @@
 
 #include "src/tint/utils/containers/hashmap.h"
 #include "src/tint/utils/containers/vector.h"
-#include "src/tint/utils/symbol/symbol.h"
 
 namespace tint {
 
diff --git a/src/tint/utils/containers/vector.h b/src/tint/utils/containers/vector.h
index 4760cb5..4f38c32 100644
--- a/src/tint/utils/containers/vector.h
+++ b/src/tint/utils/containers/vector.h
@@ -26,6 +26,7 @@
 #include "src/tint/utils/containers/slice.h"
 #include "src/tint/utils/ice/ice.h"
 #include "src/tint/utils/macros/compiler.h"
+#include "src/tint/utils/math/hash.h"
 #include "src/tint/utils/memory/bitcast.h"
 
 /// Forward declarations
@@ -863,6 +864,34 @@
     return o;
 }
 
+/// Hasher specialization for Vector
+template <typename T, size_t N>
+struct Hasher<Vector<T, N>> {
+    /// @param vector the Vector to hash
+    /// @returns a hash of the Vector
+    size_t operator()(const Vector<T, N>& vector) const {
+        auto hash = Hash(vector.Length());
+        for (auto& el : vector) {
+            hash = HashCombine(hash, el);
+        }
+        return hash;
+    }
+};
+
+/// Hasher specialization for VectorRef
+template <typename T>
+struct Hasher<VectorRef<T>> {
+    /// @param vector the VectorRef reference to hash
+    /// @returns a hash of the Vector
+    size_t operator()(const VectorRef<T>& vector) const {
+        auto hash = Hash(vector.Length());
+        for (auto& el : vector) {
+            hash = HashCombine(hash, el);
+        }
+        return hash;
+    }
+};
+
 namespace detail {
 
 /// IsVectorLike<T>::value is true if T is a Vector or VectorRef.
diff --git a/src/tint/utils/containers/vector_test.cc b/src/tint/utils/containers/vector_test.cc
index 602bc25..ab8a3e2 100644
--- a/src/tint/utils/containers/vector_test.cc
+++ b/src/tint/utils/containers/vector_test.cc
@@ -21,6 +21,7 @@
 
 #include "src/tint/utils/containers/predicates.h"
 #include "src/tint/utils/memory/bitcast.h"
+#include "src/tint/utils/text/string_stream.h"
 
 namespace tint {
 namespace {
diff --git a/src/tint/utils/diagnostic/printer.cc b/src/tint/utils/diagnostic/printer.cc
index f2c3345..7a8e9cf 100644
--- a/src/tint/utils/diagnostic/printer.cc
+++ b/src/tint/utils/diagnostic/printer.cc
@@ -14,6 +14,8 @@
 
 #include "src/tint/utils/diagnostic/printer.h"
 
+#include <string>
+
 namespace tint::diag {
 
 Printer::~Printer() = default;
diff --git a/src/tint/utils/diagnostic/printer.h b/src/tint/utils/diagnostic/printer.h
index 39e3698..0e2d89f 100644
--- a/src/tint/utils/diagnostic/printer.h
+++ b/src/tint/utils/diagnostic/printer.h
@@ -16,10 +16,9 @@
 #define SRC_TINT_UTILS_DIAGNOSTIC_PRINTER_H_
 
 #include <memory>
+#include <sstream>
 #include <string>
 
-#include "src/tint/utils/text/string_stream.h"
-
 namespace tint::diag {
 
 class List;
@@ -74,7 +73,7 @@
     void write(const std::string& str, const Style&) override;
 
   private:
-    StringStream stream;
+    std::stringstream stream;
 };
 
 }  // namespace tint::diag
diff --git a/src/tint/utils/diagnostic/source.cc b/src/tint/utils/diagnostic/source.cc
index 8565ca3..f223d62 100644
--- a/src/tint/utils/diagnostic/source.cc
+++ b/src/tint/utils/diagnostic/source.cc
@@ -18,6 +18,7 @@
 #include <string_view>
 #include <utility>
 
+#include "src/tint/utils/text/string_stream.h"
 #include "src/tint/utils/text/unicode.h"
 
 namespace tint {
@@ -121,7 +122,9 @@
 
 Source::File::~File() = default;
 
-StringStream& operator<<(StringStream& out, const Source& source) {
+std::string ToString(const Source& source) {
+    StringStream out;
+
     auto rng = source.range;
 
     if (source.file) {
@@ -171,7 +174,7 @@
             }
         }
     }
-    return out;
+    return out.str();
 }
 
 }  // namespace tint
diff --git a/src/tint/utils/diagnostic/source.h b/src/tint/utils/diagnostic/source.h
index d1ac0b3..ac3497c 100644
--- a/src/tint/utils/diagnostic/source.h
+++ b/src/tint/utils/diagnostic/source.h
@@ -193,14 +193,17 @@
     const File* file = nullptr;
 };
 
+/// @param source the input Source
+/// @returns a string that describes given source location
+std::string ToString(const Source& source);
+
 /// Writes the Source::Location to the stream.
 /// @param out the stream to write to
 /// @param loc the location to write
 /// @returns out so calls can be chained
 template <typename STREAM, typename = traits::EnableIfIsOStream<STREAM>>
 auto& operator<<(STREAM& out, const Source::Location& loc) {
-    out << loc.line << ":" << loc.column;
-    return out;
+    return out << loc.line << ":" << loc.column;
 }
 
 /// Writes the Source::Range to the stream.
@@ -209,15 +212,17 @@
 /// @returns out so calls can be chained
 template <typename STREAM, typename = traits::EnableIfIsOStream<STREAM>>
 auto& operator<<(STREAM& out, const Source::Range& range) {
-    out << "[" << range.begin << ", " << range.end << "]";
-    return out;
+    return out << "[" << range.begin << ", " << range.end << "]";
 }
 
 /// Writes the Source to the stream.
 /// @param out the stream to write to
 /// @param source the source to write
 /// @returns out so calls can be chained
-StringStream& operator<<(StringStream& out, const Source& source);
+template <typename STREAM, typename = traits::EnableIfIsOStream<STREAM>>
+auto& operator<<(STREAM& out, const Source& source) {
+    return out << ToString(source);
+}
 
 /// Writes the Source::FileContent to the stream.
 /// @param out the stream to write to
@@ -225,8 +230,7 @@
 /// @returns out so calls can be chained
 template <typename STREAM, typename = traits::EnableIfIsOStream<STREAM>>
 auto& operator<<(STREAM& out, const Source::FileContent& content) {
-    out << content.data;
-    return out;
+    return out << content.data;
 }
 
 }  // namespace tint
diff --git a/src/tint/utils/generator/text_generator.cc b/src/tint/utils/generator/text_generator.cc
index 221b249..3612fd9 100644
--- a/src/tint/utils/generator/text_generator.cc
+++ b/src/tint/utils/generator/text_generator.cc
@@ -26,20 +26,6 @@
 
 TextGenerator::~TextGenerator() = default;
 
-std::string TextGenerator::UniqueIdentifier(const std::string& /* = "" */) {
-    TINT_UNIMPLEMENTED() << "UniqueIdentifier() not overridden";
-    return "<error>";
-}
-
-std::string TextGenerator::StructName(const type::Struct* s) {
-    auto name = s->Name().Name();
-    if (name.size() > 1 && name[0] == '_' && name[1] == '_') {
-        name = tint::GetOrCreate(builtin_struct_names_, s,
-                                 [&] { return UniqueIdentifier(name.substr(2)); });
-    }
-    return name;
-}
-
 TextGenerator::LineWriter::LineWriter(TextBuffer* buf) : buffer(buf) {}
 
 TextGenerator::LineWriter::LineWriter(LineWriter&& other) {
diff --git a/src/tint/utils/generator/text_generator.h b/src/tint/utils/generator/text_generator.h
index 70e6bdb..edd0b36 100644
--- a/src/tint/utils/generator/text_generator.h
+++ b/src/tint/utils/generator/text_generator.h
@@ -20,7 +20,6 @@
 #include <utility>
 #include <vector>
 
-#include "src/tint/lang/core/type/struct.h"
 #include "src/tint/utils/diagnostic/diagnostic.h"
 #include "src/tint/utils/text/string_stream.h"
 
@@ -131,19 +130,6 @@
     /// 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.
-    /// TODO(crbug.com/tint/1992): The printers should not be creating new symbols. This should be
-    /// done as part of the IR-raise process. Remove once all writers have been moved to IR.
-    virtual std::string UniqueIdentifier(const std::string& prefix = "");
-
-    /// @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(); }
 
@@ -197,10 +183,6 @@
 
     /// 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
diff --git a/src/tint/utils/ice/ice.h b/src/tint/utils/ice/ice.h
index 63966f7..11f92a6 100644
--- a/src/tint/utils/ice/ice.h
+++ b/src/tint/utils/ice/ice.h
@@ -20,7 +20,6 @@
 #include <utility>
 
 #include "src/tint/utils/macros/compiler.h"
-#include "src/tint/utils/text/string_stream.h"
 
 namespace tint {
 
@@ -64,7 +63,7 @@
   private:
     char const* const file_;
     const size_t line_;
-    StringStream msg_;
+    std::stringstream msg_;
 };
 
 /// Function type used for registering an internal compiler error reporter
diff --git a/src/tint/utils/id/generation_id.h b/src/tint/utils/id/generation_id.h
index 6eae884..488813f 100644
--- a/src/tint/utils/id/generation_id.h
+++ b/src/tint/utils/id/generation_id.h
@@ -96,10 +96,10 @@
 
 }  // namespace detail
 
-/// TINT_ASSERT_GENERATION_IDS_EQUAL(SYSTEM, A, B) is a macro that asserts that the
+/// TINT_ASSERT_GENERATION_IDS_EQUAL(A, B) is a macro that asserts that the
 /// generation identifiers for A and B are equal.
 ///
-/// TINT_ASSERT_GENERATION_IDS_EQUAL_IF_VALID(SYSTEM, A, B) is a macro that asserts
+/// TINT_ASSERT_GENERATION_IDS_EQUAL_IF_VALID(A, B) is a macro that asserts
 /// that the generation identifiers for A and B are equal, if both A and B have
 /// valid generation identifiers.
 #if TINT_CHECK_FOR_CROSS_GENERATION_LEAKS
diff --git a/src/tint/utils/math/hash.h b/src/tint/utils/math/hash.h
index 2b8d42f..2fe6fee 100644
--- a/src/tint/utils/math/hash.h
+++ b/src/tint/utils/math/hash.h
@@ -24,7 +24,6 @@
 #include <variant>
 #include <vector>
 
-#include "src/tint/utils/containers/vector.h"
 #include "src/tint/utils/math/crc32.h"
 
 namespace tint {
@@ -111,34 +110,6 @@
     }
 };
 
-/// Hasher specialization for Vector
-template <typename T, size_t N>
-struct Hasher<Vector<T, N>> {
-    /// @param vector the Vector to hash
-    /// @returns a hash of the Vector
-    size_t operator()(const Vector<T, N>& vector) const {
-        auto hash = Hash(vector.Length());
-        for (auto& el : vector) {
-            hash = HashCombine(hash, el);
-        }
-        return hash;
-    }
-};
-
-/// Hasher specialization for VectorRef
-template <typename T>
-struct Hasher<VectorRef<T>> {
-    /// @param vector the VectorRef reference to hash
-    /// @returns a hash of the Vector
-    size_t operator()(const VectorRef<T>& vector) const {
-        auto hash = Hash(vector.Length());
-        for (auto& el : vector) {
-            hash = HashCombine(hash, el);
-        }
-        return hash;
-    }
-};
-
 /// Hasher specialization for std::tuple
 template <typename... TYPES>
 struct Hasher<std::tuple<TYPES...>> {
diff --git a/src/tint/utils/text/string_stream_test.cc b/src/tint/utils/text/string_stream_test.cc
index c5a74fc..5ba6ce0 100644
--- a/src/tint/utils/text/string_stream_test.cc
+++ b/src/tint/utils/text/string_stream_test.cc
@@ -20,9 +20,13 @@
 
 #include "gtest/gtest.h"
 
-namespace tint {
+#include "src/tint/utils/traits/traits.h"
+
+namespace tint::utils {
 namespace {
 
+static_assert(traits::IsOStream<StringStream>);
+
 using StringStreamTest = testing::Test;
 
 TEST_F(StringStreamTest, Zero) {
@@ -108,4 +112,4 @@
 }
 
 }  // namespace
-}  // namespace tint
+}  // namespace tint::utils