spirv reader: do not add duplicate constructed types

My last CL (https://dawn-review.googlesource.com/c/tint/+/49542) made it
so that AST nodes are re-created every type we resolve a spirv type id
to a tint type. This creates duplicate nodes, most of which are cleaned
up at the end of parsing. However, duplicates added as global
constructed types are not handled, so this CL makes sure we do not add
said duplicates.

Bug: tint:769
Bug: tint:724
Change-Id: Ifab46aa3b843a841c4371659dbec64891fdabc9a
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/49760
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc
index cbe0456..c440dc3 100644
--- a/src/reader/spirv/parser_impl.cc
+++ b/src/reader/spirv/parser_impl.cc
@@ -1033,10 +1033,17 @@
   if (num_non_writable_members == members.size()) {
     read_only_struct_types_.insert(result.ast->name());
   }
-  builder_.AST().AddConstructedType(result);
+  AddConstructedType(sym, result);
   return result;
 }
 
+void ParserImpl::AddConstructedType(Symbol name, typ::Type type) {
+  auto iter = constructed_types_.insert(name);
+  if (iter.second) {
+    builder_.AST().AddConstructedType(type);
+  }
+}
+
 typ::Type ParserImpl::ConvertType(uint32_t type_id,
                                   const spvtools::opt::analysis::Pointer*) {
   const auto* inst = def_use_mgr_->GetDef(type_id);
@@ -1202,11 +1209,11 @@
     return {};
   }
   const auto name = namer_.GetName(type_id);
-  auto ast_alias_type =
-      builder_.ty.alias(builder_.Symbols().Register(name), ast_underlying_type);
+  const auto sym = builder_.Symbols().Register(name);
+  auto ast_alias_type = builder_.ty.alias(sym, ast_underlying_type);
 
   // Record this new alias as the AST type for this SPIR-V ID.
-  builder_.AST().AddConstructedType(ast_alias_type);
+  AddConstructedType(sym, ast_alias_type);
 
   return ast_alias_type;
 }
diff --git a/src/reader/spirv/parser_impl.h b/src/reader/spirv/parser_impl.h
index 425e8e5..56e4afa 100644
--- a/src/reader/spirv/parser_impl.h
+++ b/src/reader/spirv/parser_impl.h
@@ -591,6 +591,11 @@
   bool ParseArrayDecorations(const spvtools::opt::analysis::Type* spv_type,
                              ast::DecorationList* decorations);
 
+  /// Adds `type` as a constructed type if it hasn't been added yet.
+  /// @param name the type's unique name
+  /// @param type the type to add
+  void AddConstructedType(Symbol name, typ::Type type);
+
   /// Creates a new `ast::Node` owned by the ProgramBuilder.
   /// @param args the arguments to pass to the type constructor
   /// @returns the node pointer
@@ -691,6 +696,10 @@
   std::unordered_map<const spvtools::opt::Instruction*, typ::Pointer>
       handle_type_;
 
+  // Set of symbols of constructed types that have been added, used to avoid
+  // adding duplicates.
+  std::unordered_set<Symbol> constructed_types_;
+
   /// Maps the SPIR-V ID of a module-scope builtin variable that should be
   /// ignored or type-converted, to its builtin kind.
   /// See also BuiltInPositionInfo which is a separate mechanism for a more