ProgramBuilder: Fixup last few uses of sem::Type*

With typ::Type.

Involves decoupling the use of named types as sub-types of other types,
otherwise ty.array("x", Structure(...)) produces an AST tree with
duplicated AST nodes.

Bug: tint:724
Change-Id: I2b4e904dc23bb554a75d4612f6543f1911f469bd
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/48693
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/BUILD.gn b/src/BUILD.gn
index ddd24b1..280a40f 100644
--- a/src/BUILD.gn
+++ b/src/BUILD.gn
@@ -387,6 +387,8 @@
     "ast/type.h",
     "ast/type_constructor_expression.cc",
     "ast/type_constructor_expression.h",
+    "ast/type_name.cc",
+    "ast/type_name.h",
     "ast/u32.cc",
     "ast/u32.h",
     "ast/uint_literal.cc",
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 605fa55..e4c6544 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -168,6 +168,8 @@
   ast/texture.h
   ast/type_constructor_expression.cc
   ast/type_constructor_expression.h
+  ast/type_name.cc
+  ast/type_name.h
   ast/ast_type.cc  # TODO(bclayton) - rename to type.cc
   ast/type.h
   ast/u32.cc
diff --git a/src/ast/type_name.cc b/src/ast/type_name.cc
new file mode 100644
index 0000000..cc1cf1e
--- /dev/null
+++ b/src/ast/type_name.cc
@@ -0,0 +1,47 @@
+// Copyright 2021 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/ast/type_name.h"
+
+#include "src/program_builder.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::ast::TypeName);
+
+namespace tint {
+namespace ast {
+
+TypeName::TypeName(ProgramID program_id, const Source& source, Symbol name)
+    : Base(program_id, source),
+      name_(name),
+      type_name_("__type_name_" + name.to_str()) {}
+
+TypeName::~TypeName() = default;
+
+TypeName::TypeName(TypeName&&) = default;
+
+std::string TypeName::type_name() const {
+  return type_name_;
+}
+
+std::string TypeName::FriendlyName(const SymbolTable& symbols) const {
+  return symbols.NameFor(name_);
+}
+
+TypeName* TypeName::Clone(CloneContext* ctx) const {
+  auto src = ctx->Clone(source());
+  return ctx->dst->create<TypeName>(src, name_);
+}
+
+}  // namespace ast
+}  // namespace tint
diff --git a/src/ast/type_name.h b/src/ast/type_name.h
new file mode 100644
index 0000000..e3759c3
--- /dev/null
+++ b/src/ast/type_name.h
@@ -0,0 +1,62 @@
+// Copyright 2021 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_AST_TYPE_NAME_H_
+#define SRC_AST_TYPE_NAME_H_
+
+#include <string>
+
+#include "src/ast/type.h"
+
+namespace tint {
+namespace ast {
+
+/// A named type (i.e. struct or alias)
+class TypeName : public Castable<TypeName, Type> {
+ public:
+  /// Constructor
+  /// @param program_id the identifier of the program that owns this node
+  /// @param source the source of this node
+  /// @param name the type name
+  TypeName(ProgramID program_id, const Source& source, Symbol name);
+  /// Move constructor
+  TypeName(TypeName&&);
+  /// Destructor
+  ~TypeName() override;
+
+  /// @return the type name
+  const Symbol& name() const { return name_; }
+
+  /// @returns the name for th type
+  std::string type_name() const override;
+
+  /// @param symbols the program's symbol table
+  /// @returns the name for this type that closely resembles how it would be
+  /// declared in WGSL.
+  std::string FriendlyName(const SymbolTable& symbols) const override;
+
+  /// Clones this type and all transitive types using the `CloneContext` `ctx`.
+  /// @param ctx the clone context
+  /// @return the newly cloned type
+  TypeName* Clone(CloneContext* ctx) const override;
+
+ private:
+  Symbol name_;
+  std::string const type_name_;
+};
+
+}  // namespace ast
+}  // namespace tint
+
+#endif  // SRC_AST_TYPE_NAME_H_
diff --git a/src/program_builder.cc b/src/program_builder.cc
index 368efca..202c0ee 100644
--- a/src/program_builder.cc
+++ b/src/program_builder.cc
@@ -16,6 +16,7 @@
 
 #include "src/ast/assignment_statement.h"
 #include "src/ast/call_statement.h"
+#include "src/ast/type_name.h"
 #include "src/ast/variable_decl_statement.h"
 #include "src/debug.h"
 #include "src/demangler.h"
@@ -91,7 +92,7 @@
 }
 
 ast::ConstructorExpression* ProgramBuilder::ConstructValueFilledWith(
-    sem::Type* type,
+    typ::Type type,
     int elem_value) {
   auto* unwrapped_type = type->UnwrapAliasIfNeeded();
   if (unwrapped_type->Is<sem::Bool>()) {
@@ -129,6 +130,17 @@
   return nullptr;
 }
 
+typ::Type ProgramBuilder::TypesBuilder::MaybeCreateTypename(
+    typ::Type type) const {
+  if (auto* alias = type.ast->As<ast::Alias>()) {
+    return {builder->create<ast::TypeName>(alias->symbol()), type.sem};
+  }
+  if (auto* str = type.ast->As<ast::Struct>()) {
+    return {builder->create<ast::TypeName>(str->name()), type.sem};
+  }
+  return type;
+}
+
 ProgramBuilder::TypesBuilder::TypesBuilder(ProgramBuilder* pb) : builder(pb) {}
 
 ast::Statement* ProgramBuilder::WrapInStatement(ast::Literal* lit) {
diff --git a/src/program_builder.h b/src/program_builder.h
index 4b00976..1b5da81 100644
--- a/src/program_builder.h
+++ b/src/program_builder.h
@@ -343,7 +343,7 @@
 
     /// @return the tint AST type for the C type `T`.
     template <typename T>
-    sem::Type* Of() const {
+    typ::Type Of() const {
       return CToAST<T>::get(this);
     }
 
@@ -558,6 +558,7 @@
     typ::Array array(typ::Type subtype,
                      uint32_t n = 0,
                      ast::DecorationList decos = {}) const {
+      subtype = MaybeCreateTypename(subtype);
       return {builder->create<ast::Array>(subtype, n, decos),
               builder->create<sem::ArrayType>(subtype, n, decos)};
     }
@@ -567,6 +568,7 @@
     /// @param stride the array stride
     /// @return the tint AST type for a array of size `n` of type `T`
     typ::Array array(typ::Type subtype, uint32_t n, uint32_t stride) const {
+      subtype = MaybeCreateTypename(subtype);
       return array(subtype, n,
                    {builder->create<ast::StrideDecoration>(stride)});
     }
@@ -590,6 +592,7 @@
     /// @returns the alias pointer
     template <typename NAME>
     typ::Alias alias(NAME&& name, typ::Type type) const {
+      type = MaybeCreateTypename(type);
       auto sym = builder->Sym(std::forward<NAME>(name));
       return {
           builder->create<ast::Alias>(sym, type),
@@ -603,6 +606,7 @@
     /// @returns the access control qualifier type
     typ::AccessControl access(ast::AccessControl::Access access,
                               typ::Type type) const {
+      type = MaybeCreateTypename(type);
       return {builder->create<ast::AccessControl>(access, type),
               builder->create<sem::AccessControl>(access, type)};
     }
@@ -612,6 +616,7 @@
     /// @return the pointer to `type` with the given ast::StorageClass
     typ::Pointer pointer(typ::Type type,
                          ast::StorageClass storage_class) const {
+      type = MaybeCreateTypename(type);
       return {builder->create<ast::Pointer>(type, storage_class),
               builder->create<sem::Pointer>(type, storage_class)};
     }
@@ -673,12 +678,18 @@
               builder->create<sem::StorageTexture>(dims, format, sem_subtype)};
     }
 
+    /// If ty is a ast::Struct or ast::Alias, the returned type is an
+    /// ast::TypeName of the given type's name, otherwise  type is returned.
+    /// @param type the type
+    /// @return either type or a pointer to a new ast::TypeName
+    typ::Type MaybeCreateTypename(typ::Type type) const;
+
    private:
     /// CToAST<T> is specialized for various `T` types and each specialization
     /// contains a single static `get()` method for obtaining the corresponding
     /// AST type for the C type `T`.
     /// `get()` has the signature:
-    ///    `static sem::Type* get(Types* t)`
+    ///    `static typ::Type get(Types* t)`
     template <typename T>
     struct CToAST {};
 
@@ -840,7 +851,7 @@
   /// @return an `ast::TypeConstructorExpression` of `type` constructed with the
   /// values `args`.
   template <typename... ARGS>
-  ast::TypeConstructorExpression* Construct(sem::Type* type, ARGS&&... args) {
+  ast::TypeConstructorExpression* Construct(typ::Type type, ARGS&&... args) {
     return create<ast::TypeConstructorExpression>(
         type, ExprList(std::forward<ARGS>(args)...));
   }
@@ -853,7 +864,7 @@
   /// @param elem_value the initial or element value (for vec and mat) to
   /// construct with
   /// @return the constructor expression
-  ast::ConstructorExpression* ConstructValueFilledWith(sem::Type* type,
+  ast::ConstructorExpression* ConstructValueFilledWith(typ::Type type,
                                                        int elem_value = 0);
 
   /// @param args the arguments for the vector constructor
@@ -994,10 +1005,11 @@
   /// @returns a `ast::Variable` with the given name, storage and type
   template <typename NAME>
   ast::Variable* Var(NAME&& name,
-                     sem::Type* type,
+                     typ::Type type,
                      ast::StorageClass storage,
                      ast::Expression* constructor = nullptr,
                      ast::DecorationList decorations = {}) {
+    type = ty.MaybeCreateTypename(type);
     return create<ast::Variable>(Sym(std::forward<NAME>(name)), storage, type,
                                  false, constructor, decorations);
   }
@@ -1012,10 +1024,11 @@
   template <typename NAME>
   ast::Variable* Var(const Source& source,
                      NAME&& name,
-                     sem::Type* type,
+                     typ::Type type,
                      ast::StorageClass storage,
                      ast::Expression* constructor = nullptr,
                      ast::DecorationList decorations = {}) {
+    type = ty.MaybeCreateTypename(type);
     return create<ast::Variable>(source, Sym(std::forward<NAME>(name)), storage,
                                  type, false, constructor, decorations);
   }
@@ -1027,9 +1040,10 @@
   /// @returns a constant `ast::Variable` with the given name and type
   template <typename NAME>
   ast::Variable* Const(NAME&& name,
-                       sem::Type* type,
+                       typ::Type type,
                        ast::Expression* constructor = nullptr,
                        ast::DecorationList decorations = {}) {
+    type = ty.MaybeCreateTypename(type);
     return create<ast::Variable>(Sym(std::forward<NAME>(name)),
                                  ast::StorageClass::kNone, type, true,
                                  constructor, decorations);
@@ -1044,9 +1058,10 @@
   template <typename NAME>
   ast::Variable* Const(const Source& source,
                        NAME&& name,
-                       sem::Type* type,
+                       typ::Type type,
                        ast::Expression* constructor = nullptr,
                        ast::DecorationList decorations = {}) {
+    type = ty.MaybeCreateTypename(type);
     return create<ast::Variable>(source, Sym(std::forward<NAME>(name)),
                                  ast::StorageClass::kNone, type, true,
                                  constructor, decorations);
@@ -1058,8 +1073,9 @@
   /// @returns a constant `ast::Variable` with the given name and type
   template <typename NAME>
   ast::Variable* Param(NAME&& name,
-                       sem::Type* type,
+                       typ::Type type,
                        ast::DecorationList decorations = {}) {
+    type = ty.MaybeCreateTypename(type);
     return create<ast::Variable>(Sym(std::forward<NAME>(name)),
                                  ast::StorageClass::kNone, type, true, nullptr,
                                  decorations);
@@ -1073,8 +1089,9 @@
   template <typename NAME>
   ast::Variable* Param(const Source& source,
                        NAME&& name,
-                       sem::Type* type,
+                       typ::Type type,
                        ast::DecorationList decorations = {}) {
+    type = ty.MaybeCreateTypename(type);
     return create<ast::Variable>(source, Sym(std::forward<NAME>(name)),
                                  ast::StorageClass::kNone, type, true, nullptr,
                                  decorations);
@@ -1089,7 +1106,7 @@
   /// global variable with the ast::Module.
   template <typename NAME>
   ast::Variable* Global(NAME&& name,
-                        sem::Type* type,
+                        typ::Type type,
                         ast::StorageClass storage,
                         ast::Expression* constructor = nullptr,
                         ast::DecorationList decorations = {}) {
@@ -1110,7 +1127,7 @@
   template <typename NAME>
   ast::Variable* Global(const Source& source,
                         NAME&& name,
-                        sem::Type* type,
+                        typ::Type type,
                         ast::StorageClass storage,
                         ast::Expression* constructor = nullptr,
                         ast::DecorationList decorations = {}) {
@@ -1263,10 +1280,11 @@
   ast::Function* Func(const Source& source,
                       NAME&& name,
                       ast::VariableList params,
-                      sem::Type* type,
+                      typ::Type type,
                       ast::StatementList body,
                       ast::DecorationList decorations = {},
                       ast::DecorationList return_type_decorations = {}) {
+    type = ty.MaybeCreateTypename(type);
     auto* func =
         create<ast::Function>(source, Sym(std::forward<NAME>(name)), params,
                               type, create<ast::BlockStatement>(body),
@@ -1287,10 +1305,11 @@
   template <typename NAME>
   ast::Function* Func(NAME&& name,
                       ast::VariableList params,
-                      sem::Type* type,
+                      typ::Type type,
                       ast::StatementList body,
                       ast::DecorationList decorations = {},
                       ast::DecorationList return_type_decorations = {}) {
+    type = ty.MaybeCreateTypename(type);
     auto* func = create<ast::Function>(Sym(std::forward<NAME>(name)), params,
                                        type, create<ast::BlockStatement>(body),
                                        decorations, return_type_decorations);
@@ -1373,8 +1392,9 @@
   template <typename NAME>
   ast::StructMember* Member(const Source& source,
                             NAME&& name,
-                            sem::Type* type,
+                            typ::Type type,
                             ast::DecorationList decorations = {}) {
+    type = ty.MaybeCreateTypename(type);
     return create<ast::StructMember>(source, Sym(std::forward<NAME>(name)),
                                      type, std::move(decorations));
   }
@@ -1386,8 +1406,9 @@
   /// @returns the struct member pointer
   template <typename NAME>
   ast::StructMember* Member(NAME&& name,
-                            sem::Type* type,
+                            typ::Type type,
                             ast::DecorationList decorations = {}) {
+    type = ty.MaybeCreateTypename(type);
     return create<ast::StructMember>(source_, Sym(std::forward<NAME>(name)),
                                      type, std::move(decorations));
   }
@@ -1398,7 +1419,8 @@
   /// @param type the struct member type
   /// @returns the struct member pointer
   template <typename NAME>
-  ast::StructMember* Member(uint32_t offset, NAME&& name, sem::Type* type) {
+  ast::StructMember* Member(uint32_t offset, NAME&& name, typ::Type type) {
+    type = ty.MaybeCreateTypename(type);
     return create<ast::StructMember>(
         source_, Sym(std::forward<NAME>(name)), type,
         ast::DecorationList{
@@ -1665,31 +1687,31 @@
 // Various template specializations for ProgramBuilder::TypesBuilder::CToAST.
 template <>
 struct ProgramBuilder::TypesBuilder::CToAST<ProgramBuilder::i32> {
-  static sem::Type* get(const ProgramBuilder::TypesBuilder* t) {
+  static typ::Type get(const ProgramBuilder::TypesBuilder* t) {
     return t->i32();
   }
 };
 template <>
 struct ProgramBuilder::TypesBuilder::CToAST<ProgramBuilder::u32> {
-  static sem::Type* get(const ProgramBuilder::TypesBuilder* t) {
+  static typ::Type get(const ProgramBuilder::TypesBuilder* t) {
     return t->u32();
   }
 };
 template <>
 struct ProgramBuilder::TypesBuilder::CToAST<ProgramBuilder::f32> {
-  static sem::Type* get(const ProgramBuilder::TypesBuilder* t) {
+  static typ::Type get(const ProgramBuilder::TypesBuilder* t) {
     return t->f32();
   }
 };
 template <>
 struct ProgramBuilder::TypesBuilder::CToAST<bool> {
-  static sem::Type* get(const ProgramBuilder::TypesBuilder* t) {
+  static typ::Type get(const ProgramBuilder::TypesBuilder* t) {
     return t->bool_();
   }
 };
 template <>
 struct ProgramBuilder::TypesBuilder::CToAST<void> {
-  static sem::Type* get(const ProgramBuilder::TypesBuilder* t) {
+  static typ::Type get(const ProgramBuilder::TypesBuilder* t) {
     return t->void_();
   }
 };