writer/spirv: Begin migration to ast::Types

The SPIR-V writer doesn't really care much for ast::Types, so most of the work here is repointing the logic to fetch the resolved, semantic type.

Bug: tint:724
Change-Id: I7647e17b015bac8394bc0fc76daceb7c0a391a47
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/49528
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index 98f10e3..cc2d184 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -508,7 +508,9 @@
   return 0;
 }
 
-bool Builder::GenerateFunction(ast::Function* func) {
+bool Builder::GenerateFunction(ast::Function* func_ast) {
+  auto* func = builder_.Sem().Get(func_ast);
+
   uint32_t func_type_id = GenerateFunctionTypeIfNeeded(func);
   if (func_type_id == 0) {
     return false;
@@ -519,9 +521,9 @@
 
   push_debug(spv::Op::OpName,
              {Operand::Int(func_id),
-              Operand::String(builder_.Symbols().NameFor(func->symbol()))});
+              Operand::String(builder_.Symbols().NameFor(func_ast->symbol()))});
 
-  auto ret_id = GenerateTypeIfNeeded(func->return_type());
+  auto ret_id = GenerateTypeIfNeeded(func->ReturnType());
   if (ret_id == 0) {
     return false;
   }
@@ -534,51 +536,50 @@
        Operand::Int(func_type_id)}};
 
   InstructionList params;
-  for (auto* param : func->params()) {
+  for (auto* param : func->Parameters()) {
     auto param_op = result_op();
     auto param_id = param_op.to_i();
 
-    auto param_type_id =
-        GenerateTypeIfNeeded(builder_.Sem().Get(param)->Type());
+    auto param_type_id = GenerateTypeIfNeeded(param->Type());
     if (param_type_id == 0) {
       return false;
     }
 
-    push_debug(spv::Op::OpName,
-               {Operand::Int(param_id),
-                Operand::String(builder_.Symbols().NameFor(param->symbol()))});
+    push_debug(spv::Op::OpName, {Operand::Int(param_id),
+                                 Operand::String(builder_.Symbols().NameFor(
+                                     param->Declaration()->symbol()))});
     params.push_back(Instruction{spv::Op::OpFunctionParameter,
                                  {Operand::Int(param_type_id), param_op}});
 
-    scope_stack_.set(param->symbol(), param_id);
+    scope_stack_.set(param->Declaration()->symbol(), param_id);
   }
 
   push_function(Function{definition_inst, result_op(), std::move(params)});
 
-  for (auto* stmt : *func->body()) {
+  for (auto* stmt : *func_ast->body()) {
     if (!GenerateStatement(stmt)) {
       return false;
     }
   }
 
-  if (func->IsEntryPoint()) {
-    if (!GenerateEntryPoint(func, func_id)) {
+  if (func_ast->IsEntryPoint()) {
+    if (!GenerateEntryPoint(func_ast, func_id)) {
       return false;
     }
-    if (!GenerateExecutionModes(func, func_id)) {
+    if (!GenerateExecutionModes(func_ast, func_id)) {
       return false;
     }
   }
 
   scope_stack_.pop_scope();
 
-  func_symbol_to_id_[func->symbol()] = func_id;
+  func_symbol_to_id_[func_ast->symbol()] = func_id;
 
   return true;
 }
 
-uint32_t Builder::GenerateFunctionTypeIfNeeded(ast::Function* func) {
-  auto val = type_name_to_id_.find(func->type_name());
+uint32_t Builder::GenerateFunctionTypeIfNeeded(const sem::Function* func) {
+  auto val = type_name_to_id_.find(func->Declaration()->type_name());
   if (val != type_name_to_id_.end()) {
     return val->second;
   }
@@ -586,15 +587,14 @@
   auto func_op = result_op();
   auto func_type_id = func_op.to_i();
 
-  auto ret_id = GenerateTypeIfNeeded(func->return_type());
+  auto ret_id = GenerateTypeIfNeeded(func->ReturnType());
   if (ret_id == 0) {
     return 0;
   }
 
   OperandList ops = {func_op, Operand::Int(ret_id)};
-  for (auto* param : func->params()) {
-    auto param_type_id =
-        GenerateTypeIfNeeded(builder_.Sem().Get(param)->Type());
+  for (auto* param : func->Parameters()) {
+    auto param_type_id = GenerateTypeIfNeeded(param->Type());
     if (param_type_id == 0) {
       return 0;
     }
@@ -603,7 +603,7 @@
 
   push_type(spv::Op::OpTypeFunction, std::move(ops));
 
-  type_name_to_id_[func->type_name()] = func_type_id;
+  type_name_to_id_[func->Declaration()->type_name()] = func_type_id;
   return func_type_id;
 }
 
@@ -1217,7 +1217,7 @@
   }
 
   auto* tc = constructor->As<ast::TypeConstructorExpression>();
-  auto* result_type = tc->type()->UnwrapAll();
+  auto* result_type = TypeOf(tc)->UnwrapAll();
   for (size_t i = 0; i < tc->values().size(); ++i) {
     auto* e = tc->values()[i];
 
@@ -1253,7 +1253,7 @@
     } else if (auto* arr = subtype->As<sem::ArrayType>()) {
       subtype = arr->type()->UnwrapAll();
     } else if (auto* str = subtype->As<sem::StructType>()) {
-      subtype = str->impl()->members()[i]->type()->UnwrapAll();
+      subtype = builder_.Sem().Get(str)->Members()[i]->Type()->UnwrapAll();
     }
     if (subtype != TypeOf(sc)->UnwrapAll()) {
       return false;
@@ -1267,15 +1267,17 @@
     bool is_global_init) {
   auto& values = init->values();
 
+  auto* result_type = TypeOf(init);
+
   // Generate the zero initializer if there are no values provided.
   if (values.empty()) {
-    return GenerateConstantNullIfNeeded(init->type()->UnwrapPtrIfNeeded());
+    return GenerateConstantNullIfNeeded(result_type->UnwrapPtrIfNeeded());
   }
 
   std::ostringstream out;
   out << "__const";
 
-  auto* result_type = init->type()->UnwrapAll();
+  result_type = result_type->UnwrapAll();
   bool constructor_is_const = is_constructor_const(init, is_global_init);
   if (has_error()) {
     return 0;
@@ -1298,7 +1300,7 @@
     return GenerateCastOrCopyOrPassthrough(result_type, values[0]);
   }
 
-  auto type_id = GenerateTypeIfNeeded(init->type());
+  auto type_id = GenerateTypeIfNeeded(result_type);
   if (type_id == 0) {
     return 0;
   }
@@ -1426,7 +1428,7 @@
   return result.to_i();
 }
 
-uint32_t Builder::GenerateCastOrCopyOrPassthrough(sem::Type* to_type,
+uint32_t Builder::GenerateCastOrCopyOrPassthrough(const sem::Type* to_type,
                                                   ast::Expression* from_expr) {
   auto result = result_op();
   auto result_id = result.to_i();
@@ -1598,7 +1600,7 @@
   return result_id;
 }
 
-uint32_t Builder::GenerateConstantNullIfNeeded(sem::Type* type) {
+uint32_t Builder::GenerateConstantNullIfNeeded(const sem::Type* type) {
   auto type_id = GenerateTypeIfNeeded(type);
   if (type_id == 0) {
     return 0;
@@ -2413,12 +2415,15 @@
       if (TypeOf(arg(Usage::kLevel))->Is<sem::I32>()) {
         // Depth textures have i32 parameters for the level, but SPIR-V expects
         // F32. Cast.
-        auto* f32 = builder_.create<sem::F32>();
-        ast::TypeConstructorExpression cast(ProgramID(), Source{}, f32,
-                                            {arg(Usage::kLevel)});
-        level = Operand::Int(GenerateExpression(&cast));
-        if (level.to_i() == 0) {
-          return false;
+        auto f32_type_id = GenerateTypeIfNeeded(builder_.create<sem::F32>());
+        if (f32_type_id == 0) {
+          return 0;
+        }
+        level = result_op();
+        if (!push_function_inst(
+                spv::Op::OpConvertSToF,
+                {Operand::Int(f32_type_id), level, gen_arg(Usage::kLevel)})) {
+          return 0;
         }
       } else {
         level = gen_arg(Usage::kLevel);
@@ -2920,7 +2925,7 @@
   return GenerateFunctionVariable(stmt->variable());
 }
 
-uint32_t Builder::GenerateTypeIfNeeded(sem::Type* type) {
+uint32_t Builder::GenerateTypeIfNeeded(const sem::Type* type) {
   if (type == nullptr) {
     error_ = "attempting to generate type from null type";
     return 0;
@@ -3002,7 +3007,7 @@
 }
 
 // TODO(tommek): Cover multisampled textures here when they're included in AST
-bool Builder::GenerateTextureType(sem::Texture* texture,
+bool Builder::GenerateTextureType(const sem::Texture* texture,
                                   const Operand& result) {
   uint32_t array_literal = 0u;
   const auto dim = texture->dim();
@@ -3080,7 +3085,8 @@
   return true;
 }
 
-bool Builder::GenerateArrayType(sem::ArrayType* ary, const Operand& result) {
+bool Builder::GenerateArrayType(const sem::ArrayType* ary,
+                                const Operand& result) {
   auto elem_type = GenerateTypeIfNeeded(ary->type());
   if (elem_type == 0) {
     return false;
@@ -3110,7 +3116,8 @@
   return true;
 }
 
-bool Builder::GenerateMatrixType(sem::Matrix* mat, const Operand& result) {
+bool Builder::GenerateMatrixType(const sem::Matrix* mat,
+                                 const Operand& result) {
   sem::Vector col_type(mat->type(), mat->rows());
   auto col_type_id = GenerateTypeIfNeeded(&col_type);
   if (has_error()) {
@@ -3122,7 +3129,8 @@
   return true;
 }
 
-bool Builder::GeneratePointerType(sem::Pointer* ptr, const Operand& result) {
+bool Builder::GeneratePointerType(const sem::Pointer* ptr,
+                                  const Operand& result) {
   auto pointee_id = GenerateTypeIfNeeded(ptr->type());
   if (pointee_id == 0) {
     return false;
@@ -3140,7 +3148,7 @@
   return true;
 }
 
-bool Builder::GenerateStructType(sem::StructType* struct_type,
+bool Builder::GenerateStructType(const sem::StructType* struct_type,
                                  ast::AccessControl::Access access_control,
                                  const Operand& result) {
   auto struct_id = result.to_i();
@@ -3212,7 +3220,7 @@
        Operand::Int(SpvDecorationOffset), Operand::Int(sem_member->Offset())});
 
   // Infer and emit matrix layout.
-  auto* matrix_type = GetNestedMatrixType(member->type());
+  auto* matrix_type = GetNestedMatrixType(sem_member->Type());
   if (matrix_type) {
     push_annot(spv::Op::OpMemberDecorate,
                {Operand::Int(struct_id), Operand::Int(idx),
@@ -3229,10 +3237,11 @@
                 Operand::Int(effective_row_count * scalar_elem_size)});
   }
 
-  return GenerateTypeIfNeeded(member->type());
+  return GenerateTypeIfNeeded(sem_member->Type());
 }
 
-bool Builder::GenerateVectorType(sem::Vector* vec, const Operand& result) {
+bool Builder::GenerateVectorType(const sem::Vector* vec,
+                                 const Operand& result) {
   auto type_id = GenerateTypeIfNeeded(vec->type());
   if (has_error()) {
     return false;
diff --git a/src/writer/spirv/builder.h b/src/writer/spirv/builder.h
index 7e45e24..e8c2a5d 100644
--- a/src/writer/spirv/builder.h
+++ b/src/writer/spirv/builder.h
@@ -258,7 +258,7 @@
   /// Generates a function type if not already created
   /// @param func the function to generate for
   /// @returns the ID to use for the function type. Returns 0 on failure.
-  uint32_t GenerateFunctionTypeIfNeeded(ast::Function* func);
+  uint32_t GenerateFunctionTypeIfNeeded(const sem::Function* func);
   /// Generates access control annotations if needed
   /// @param type the type to generate for
   /// @param struct_id the struct id
@@ -381,7 +381,7 @@
   /// @param to_type the type we're casting too
   /// @param from_expr the expression to cast
   /// @returns the expression ID on success or 0 otherwise
-  uint32_t GenerateCastOrCopyOrPassthrough(sem::Type* to_type,
+  uint32_t GenerateCastOrCopyOrPassthrough(const sem::Type* to_type,
                                            ast::Expression* from_expr);
   /// Generates a loop statement
   /// @param stmt the statement to generate
@@ -423,33 +423,33 @@
   /// Generates a type if not already created
   /// @param type the type to create
   /// @returns the ID to use for the given type. Returns 0 on unknown type.
-  uint32_t GenerateTypeIfNeeded(sem::Type* type);
+  uint32_t GenerateTypeIfNeeded(const sem::Type* type);
   /// Generates a texture type declaration
   /// @param texture the texture to generate
   /// @param result the result operand
   /// @returns true if the texture was successfully generated
-  bool GenerateTextureType(sem::Texture* texture, const Operand& result);
+  bool GenerateTextureType(const sem::Texture* texture, const Operand& result);
   /// Generates an array type declaration
   /// @param ary the array to generate
   /// @param result the result operand
   /// @returns true if the array was successfully generated
-  bool GenerateArrayType(sem::ArrayType* ary, const Operand& result);
+  bool GenerateArrayType(const sem::ArrayType* ary, const Operand& result);
   /// Generates a matrix type declaration
   /// @param mat the matrix to generate
   /// @param result the result operand
   /// @returns true if the matrix was successfully generated
-  bool GenerateMatrixType(sem::Matrix* mat, const Operand& result);
+  bool GenerateMatrixType(const sem::Matrix* mat, const Operand& result);
   /// Generates a pointer type declaration
   /// @param ptr the pointer type to generate
   /// @param result the result operand
   /// @returns true if the pointer was successfully generated
-  bool GeneratePointerType(sem::Pointer* ptr, const Operand& result);
+  bool GeneratePointerType(const sem::Pointer* ptr, const Operand& result);
   /// Generates a vector type declaration
   /// @param struct_type the vector to generate
   /// @param access_control the access controls to assign to the struct
   /// @param result the result operand
   /// @returns true if the vector was successfully generated
-  bool GenerateStructType(sem::StructType* struct_type,
+  bool GenerateStructType(const sem::StructType* struct_type,
                           ast::AccessControl::Access access_control,
                           const Operand& result);
   /// Generates a struct member
@@ -468,7 +468,7 @@
   /// @param vec the vector to generate
   /// @param result the result operand
   /// @returns true if the vector was successfully generated
-  bool GenerateVectorType(sem::Vector* vec, const Operand& result);
+  bool GenerateVectorType(const sem::Vector* vec, const Operand& result);
 
   /// Converts AST image format to SPIR-V and pushes an appropriate capability.
   /// @param format AST image format type
@@ -500,7 +500,7 @@
   /// Generates a constant-null of the given type, if needed
   /// @param type the type of the constant null to generate.
   /// @returns the ID on success or 0 on failure
-  uint32_t GenerateConstantNullIfNeeded(sem::Type* type);
+  uint32_t GenerateConstantNullIfNeeded(const sem::Type* type);
 
   ProgramBuilder builder_;
   std::string error_;
diff --git a/src/writer/spirv/builder_global_variable_test.cc b/src/writer/spirv/builder_global_variable_test.cc
index 3551e36..4917a1a 100644
--- a/src/writer/spirv/builder_global_variable_test.cc
+++ b/src/writer/spirv/builder_global_variable_test.cc
@@ -430,6 +430,7 @@
   auto A = Structure("A", {Member("a", ty.i32())},
                      {create<ast::StructBlockDecoration>()});
   auto B = ty.alias("B", A);
+  AST().AddConstructedType(B);
   auto ac = ty.access(ast::AccessControl::kReadOnly, B);
   auto* var = Global("b", ac, ast::StorageClass::kStorage);
 
@@ -463,6 +464,7 @@
                      {create<ast::StructBlockDecoration>()});
   auto ac = ty.access(ast::AccessControl::kReadOnly, A);
   auto B = ty.alias("B", ac);
+  AST().AddConstructedType(B);
   auto* var = Global("b", B, ast::StorageClass::kStorage);
 
   spirv::Builder& b = Build();
@@ -580,13 +582,14 @@
   // var<uniform_constant> a : [[access(read)]] texture_storage_2d<r32uint>;
   // var<uniform_constant> b : [[access(write)]] texture_storage_2d<r32uint>;
 
-  auto st = ty.storage_texture(ast::TextureDimension::k2d,
-                               ast::ImageFormat::kR32Uint);
-
-  auto type_a = ty.access(ast::AccessControl::kReadOnly, st);
+  auto type_a = ty.access(ast::AccessControl::kReadOnly,
+                          ty.storage_texture(ast::TextureDimension::k2d,
+                                             ast::ImageFormat::kR32Uint));
   auto* var_a = Global("a", type_a, ast::StorageClass::kUniformConstant);
 
-  auto type_b = ty.access(ast::AccessControl::kWriteOnly, st);
+  auto type_b = ty.access(ast::AccessControl::kWriteOnly,
+                          ty.storage_texture(ast::TextureDimension::k2d,
+                                             ast::ImageFormat::kR32Uint));
   auto* var_b = Global("b", type_b, ast::StorageClass::kUniformConstant);
 
   spirv::Builder& b = Build();
diff --git a/src/writer/spirv/builder_type_test.cc b/src/writer/spirv/builder_type_test.cc
index eb5fbb0..0a75c58 100644
--- a/src/writer/spirv/builder_type_test.cc
+++ b/src/writer/spirv/builder_type_test.cc
@@ -499,7 +499,7 @@
 }
 
 TEST_F(BuilderTest_Type, GenerateU32) {
-  auto u32 = ty.u32();
+  auto* u32 = create<sem::U32>();
 
   spirv::Builder& b = Build();
 
@@ -513,7 +513,7 @@
 }
 
 TEST_F(BuilderTest_Type, ReturnsGeneratedU32) {
-  auto u32 = ty.u32();
+  auto* u32 = create<sem::U32>();
   auto f32 = ty.f32();
 
   spirv::Builder& b = Build();
@@ -527,7 +527,7 @@
 }
 
 TEST_F(BuilderTest_Type, GenerateVector) {
-  auto vec = ty.vec3<f32>();
+  auto* vec = create<sem::Vector>(create<sem::F32>(), 3);
 
   spirv::Builder& b = Build();
 
@@ -556,7 +556,7 @@
 }
 
 TEST_F(BuilderTest_Type, GenerateVoid) {
-  auto void_ = ty.void_();
+  auto* void_ = create<sem::Void>();
 
   spirv::Builder& b = Build();
 
@@ -570,7 +570,7 @@
 }
 
 TEST_F(BuilderTest_Type, ReturnsGeneratedVoid) {
-  auto void_ = ty.void_();
+  auto* void_ = create<sem::Void>();
   auto i32 = ty.i32();
 
   spirv::Builder& b = Build();
@@ -616,11 +616,11 @@
         PtrData{ast::StorageClass::kFunction, SpvStorageClassFunction}));
 
 TEST_F(BuilderTest_Type, DepthTexture_Generate_2d) {
-  sem::DepthTexture two_d(ast::TextureDimension::k2d);
+  auto* two_d = create<sem::DepthTexture>(ast::TextureDimension::k2d);
 
   spirv::Builder& b = Build();
 
-  auto id_two_d = b.GenerateTypeIfNeeded(&two_d);
+  auto id_two_d = b.GenerateTypeIfNeeded(two_d);
   ASSERT_FALSE(b.has_error()) << b.error();
   EXPECT_EQ(1u, id_two_d);
 
@@ -630,11 +630,12 @@
 }
 
 TEST_F(BuilderTest_Type, DepthTexture_Generate_2dArray) {
-  sem::DepthTexture two_d_array(ast::TextureDimension::k2dArray);
+  auto* two_d_array =
+      create<sem::DepthTexture>(ast::TextureDimension::k2dArray);
 
   spirv::Builder& b = Build();
 
-  auto id_two_d_array = b.GenerateTypeIfNeeded(&two_d_array);
+  auto id_two_d_array = b.GenerateTypeIfNeeded(two_d_array);
   ASSERT_FALSE(b.has_error()) << b.error();
   EXPECT_EQ(1u, id_two_d_array);
 
@@ -644,11 +645,11 @@
 }
 
 TEST_F(BuilderTest_Type, DepthTexture_Generate_Cube) {
-  sem::DepthTexture cube(ast::TextureDimension::kCube);
+  auto* cube = create<sem::DepthTexture>(ast::TextureDimension::kCube);
 
   spirv::Builder& b = Build();
 
-  auto id_cube = b.GenerateTypeIfNeeded(&cube);
+  auto id_cube = b.GenerateTypeIfNeeded(cube);
   ASSERT_FALSE(b.has_error()) << b.error();
   EXPECT_EQ(1u, id_cube);
 
@@ -659,11 +660,12 @@
 }
 
 TEST_F(BuilderTest_Type, DepthTexture_Generate_CubeArray) {
-  sem::DepthTexture cube_array(ast::TextureDimension::kCubeArray);
+  auto* cube_array =
+      create<sem::DepthTexture>(ast::TextureDimension::kCubeArray);
 
   spirv::Builder& b = Build();
 
-  auto id_cube_array = b.GenerateTypeIfNeeded(&cube_array);
+  auto id_cube_array = b.GenerateTypeIfNeeded(cube_array);
   ASSERT_FALSE(b.has_error()) << b.error();
   EXPECT_EQ(1u, id_cube_array);
 
@@ -676,11 +678,12 @@
 }
 
 TEST_F(BuilderTest_Type, MultisampledTexture_Generate_2d_i32) {
-  sem::MultisampledTexture ms(ast::TextureDimension::k2d, ty.i32());
+  auto i32 = ty.i32();
+  auto* ms = create<sem::MultisampledTexture>(ast::TextureDimension::k2d, i32);
 
   spirv::Builder& b = Build();
 
-  EXPECT_EQ(1u, b.GenerateTypeIfNeeded(&ms));
+  EXPECT_EQ(1u, b.GenerateTypeIfNeeded(ms));
   ASSERT_FALSE(b.has_error()) << b.error();
   EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeInt 32 1
 %1 = OpTypeImage %2 2D 0 0 1 1 Unknown
@@ -688,11 +691,12 @@
 }
 
 TEST_F(BuilderTest_Type, MultisampledTexture_Generate_2d_u32) {
-  sem::MultisampledTexture ms(ast::TextureDimension::k2d, ty.u32());
+  auto* u32 = create<sem::U32>();
+  auto* ms = create<sem::MultisampledTexture>(ast::TextureDimension::k2d, u32);
 
   spirv::Builder& b = Build();
 
-  EXPECT_EQ(b.GenerateTypeIfNeeded(&ms), 1u);
+  EXPECT_EQ(b.GenerateTypeIfNeeded(ms), 1u);
   ASSERT_FALSE(b.has_error()) << b.error();
   EXPECT_EQ(DumpInstructions(b.types()),
             R"(%2 = OpTypeInt 32 0
@@ -701,11 +705,12 @@
 }
 
 TEST_F(BuilderTest_Type, MultisampledTexture_Generate_2d_f32) {
-  sem::MultisampledTexture ms(ast::TextureDimension::k2d, ty.f32());
+  auto f32 = ty.f32();
+  auto* ms = create<sem::MultisampledTexture>(ast::TextureDimension::k2d, f32);
 
   spirv::Builder& b = Build();
 
-  EXPECT_EQ(b.GenerateTypeIfNeeded(&ms), 1u);
+  EXPECT_EQ(b.GenerateTypeIfNeeded(ms), 1u);
   ASSERT_FALSE(b.has_error()) << b.error();
   EXPECT_EQ(DumpInstructions(b.types()),
             R"(%2 = OpTypeFloat 32
@@ -714,7 +719,7 @@
 }
 
 TEST_F(BuilderTest_Type, SampledTexture_Generate_1d_i32) {
-  auto s = ty.sampled_texture(ast::TextureDimension::k1d, ty.i32());
+  auto* s = create<sem::SampledTexture>(ast::TextureDimension::k1d, ty.i32());
 
   spirv::Builder& b = Build();
 
@@ -731,7 +736,8 @@
 }
 
 TEST_F(BuilderTest_Type, SampledTexture_Generate_1d_u32) {
-  auto s = ty.sampled_texture(ast::TextureDimension::k1d, ty.u32());
+  auto* u32 = create<sem::U32>();
+  auto* s = create<sem::SampledTexture>(ast::TextureDimension::k1d, u32);
 
   spirv::Builder& b = Build();
 
@@ -748,7 +754,7 @@
 }
 
 TEST_F(BuilderTest_Type, SampledTexture_Generate_1d_f32) {
-  auto s = ty.sampled_texture(ast::TextureDimension::k1d, ty.f32());
+  auto* s = create<sem::SampledTexture>(ast::TextureDimension::k1d, ty.f32());
 
   spirv::Builder& b = Build();
 
@@ -765,7 +771,7 @@
 }
 
 TEST_F(BuilderTest_Type, SampledTexture_Generate_2d) {
-  auto s = ty.sampled_texture(ast::TextureDimension::k2d, ty.f32());
+  auto* s = create<sem::SampledTexture>(ast::TextureDimension::k2d, ty.f32());
 
   spirv::Builder& b = Build();
 
@@ -778,7 +784,8 @@
 }
 
 TEST_F(BuilderTest_Type, SampledTexture_Generate_2d_array) {
-  auto s = ty.sampled_texture(ast::TextureDimension::k2dArray, ty.f32());
+  auto* s =
+      create<sem::SampledTexture>(ast::TextureDimension::k2dArray, ty.f32());
 
   spirv::Builder& b = Build();
 
@@ -791,7 +798,7 @@
 }
 
 TEST_F(BuilderTest_Type, SampledTexture_Generate_3d) {
-  auto s = ty.sampled_texture(ast::TextureDimension::k3d, ty.f32());
+  auto* s = create<sem::SampledTexture>(ast::TextureDimension::k3d, ty.f32());
 
   spirv::Builder& b = Build();
 
@@ -804,7 +811,7 @@
 }
 
 TEST_F(BuilderTest_Type, SampledTexture_Generate_Cube) {
-  auto s = ty.sampled_texture(ast::TextureDimension::kCube, ty.f32());
+  auto* s = create<sem::SampledTexture>(ast::TextureDimension::kCube, ty.f32());
 
   spirv::Builder& b = Build();
 
@@ -818,7 +825,8 @@
 }
 
 TEST_F(BuilderTest_Type, SampledTexture_Generate_CubeArray) {
-  auto s = ty.sampled_texture(ast::TextureDimension::kCubeArray, ty.f32());
+  auto* s =
+      create<sem::SampledTexture>(ast::TextureDimension::kCubeArray, ty.f32());
 
   spirv::Builder& b = Build();
 
@@ -834,8 +842,9 @@
 }
 
 TEST_F(BuilderTest_Type, StorageTexture_Generate_1d) {
-  auto s = ty.storage_texture(ast::TextureDimension::k1d,
-                              ast::ImageFormat::kR32Float);
+  auto* s = create<sem::StorageTexture>(
+      ast::TextureDimension::k1d, ast::ImageFormat::kR32Float,
+      sem::StorageTexture::SubtypeFor(ast::ImageFormat::kR32Float, Types()));
   auto ac = ty.access(ast::AccessControl::kReadOnly, s);
 
   Global("test_var", ac, ast::StorageClass::kInput);
@@ -850,8 +859,9 @@
 }
 
 TEST_F(BuilderTest_Type, StorageTexture_Generate_2d) {
-  auto s = ty.storage_texture(ast::TextureDimension::k2d,
-                              ast::ImageFormat::kR32Float);
+  auto* s = create<sem::StorageTexture>(
+      ast::TextureDimension::k2d, ast::ImageFormat::kR32Float,
+      sem::StorageTexture::SubtypeFor(ast::ImageFormat::kR32Float, Types()));
   auto ac = ty.access(ast::AccessControl::kReadOnly, s);
 
   Global("test_var", ac, ast::StorageClass::kInput);
@@ -866,8 +876,9 @@
 }
 
 TEST_F(BuilderTest_Type, StorageTexture_Generate_2dArray) {
-  auto s = ty.storage_texture(ast::TextureDimension::k2dArray,
-                              ast::ImageFormat::kR32Float);
+  auto* s = create<sem::StorageTexture>(
+      ast::TextureDimension::k2dArray, ast::ImageFormat::kR32Float,
+      sem::StorageTexture::SubtypeFor(ast::ImageFormat::kR32Float, Types()));
   auto ac = ty.access(ast::AccessControl::kReadOnly, s);
 
   Global("test_var", ac, ast::StorageClass::kInput);
@@ -882,8 +893,9 @@
 }
 
 TEST_F(BuilderTest_Type, StorageTexture_Generate_3d) {
-  auto s = ty.storage_texture(ast::TextureDimension::k3d,
-                              ast::ImageFormat::kR32Float);
+  auto* s = create<sem::StorageTexture>(
+      ast::TextureDimension::k3d, ast::ImageFormat::kR32Float,
+      sem::StorageTexture::SubtypeFor(ast::ImageFormat::kR32Float, Types()));
   auto ac = ty.access(ast::AccessControl::kReadOnly, s);
 
   Global("test_var", ac, ast::StorageClass::kInput);
@@ -899,8 +911,9 @@
 
 TEST_F(BuilderTest_Type,
        StorageTexture_Generate_SampledTypeFloat_Format_r32float) {
-  auto s = ty.storage_texture(ast::TextureDimension::k2d,
-                              ast::ImageFormat::kR32Float);
+  auto* s = create<sem::StorageTexture>(
+      ast::TextureDimension::k2d, ast::ImageFormat::kR32Float,
+      sem::StorageTexture::SubtypeFor(ast::ImageFormat::kR32Float, Types()));
   auto ac = ty.access(ast::AccessControl::kReadOnly, s);
 
   Global("test_var", ac, ast::StorageClass::kInput);
@@ -916,8 +929,9 @@
 
 TEST_F(BuilderTest_Type,
        StorageTexture_Generate_SampledTypeSint_Format_r32sint) {
-  auto s = ty.storage_texture(ast::TextureDimension::k2d,
-                              ast::ImageFormat::kR32Sint);
+  auto* s = create<sem::StorageTexture>(
+      ast::TextureDimension::k2d, ast::ImageFormat::kR32Sint,
+      sem::StorageTexture::SubtypeFor(ast::ImageFormat::kR32Sint, Types()));
   auto ac = ty.access(ast::AccessControl::kReadOnly, s);
 
   Global("test_var", ac, ast::StorageClass::kInput);
@@ -933,8 +947,9 @@
 
 TEST_F(BuilderTest_Type,
        StorageTexture_Generate_SampledTypeUint_Format_r32uint) {
-  auto s = ty.storage_texture(ast::TextureDimension::k2d,
-                              ast::ImageFormat::kR32Uint);
+  auto* s = create<sem::StorageTexture>(
+      ast::TextureDimension::k2d, ast::ImageFormat::kR32Uint,
+      sem::StorageTexture::SubtypeFor(ast::ImageFormat::kR32Uint, Types()));
   auto ac = ty.access(ast::AccessControl::kReadOnly, s);
 
   Global("test_var", ac, ast::StorageClass::kInput);