[tint][ir] Change Var::Type() to return type::Pointer*

The type of a 'var' is always a pointer, including textures and
samplers.

Avoids a bunch of dynamic casts.

Change-Id: Ib334f68f000f60eaf09cba6c98e0b6e90abe9498
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/136440
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: James Price <jrprice@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
diff --git a/src/tint/ir/builder.cc b/src/tint/ir/builder.cc
index ab46603..b42ee59 100644
--- a/src/tint/ir/builder.cc
+++ b/src/tint/ir/builder.cc
@@ -207,7 +207,7 @@
     return ir.values.Create<ir::Store>(to, from);
 }
 
-ir::Var* Builder::Declare(const type::Type* type) {
+ir::Var* Builder::Declare(const type::Pointer* type) {
     return ir.values.Create<ir::Var>(type);
 }
 
diff --git a/src/tint/ir/builder.h b/src/tint/ir/builder.h
index c4788e5..6e04bb8 100644
--- a/src/tint/ir/builder.h
+++ b/src/tint/ir/builder.h
@@ -339,7 +339,7 @@
     /// Creates a new `var` declaration
     /// @param type the var type
     /// @returns the instruction
-    ir::Var* Declare(const type::Type* type);
+    ir::Var* Declare(const type::Pointer* type);
 
     /// Creates a return instruction
     /// @param func the function being returned
diff --git a/src/tint/ir/from_program.cc b/src/tint/ir/from_program.cc
index 2f01fb1..ecab124 100644
--- a/src/tint/ir/from_program.cc
+++ b/src/tint/ir/from_program.cc
@@ -944,8 +944,8 @@
         // The access result type should match the source result type. If the source is a pointer,
         // we generate a pointer.
         const type::Type* ty = nullptr;
-        if (info.object->Type()->Is<type::Pointer>() && !info.result_type->Is<type::Pointer>()) {
-            auto* ptr = info.object->Type()->As<type::Pointer>();
+        if (auto* ptr = info.object->Type()->As<type::Pointer>();
+            ptr && !info.result_type->Is<type::Pointer>()) {
             ty = builder_.ir.Types().pointer(info.result_type, ptr->AddressSpace(), ptr->Access());
         } else {
             ty = info.result_type;
diff --git a/src/tint/ir/ir_test_helper.h b/src/tint/ir/ir_test_helper.h
index a7826ec..0406606 100644
--- a/src/tint/ir/ir_test_helper.h
+++ b/src/tint/ir/ir_test_helper.h
@@ -32,6 +32,8 @@
     Module mod;
     /// The IR builder
     Builder b{mod};
+    /// The type manager
+    type::Manager& ty{mod.Types()};
 };
 
 using IRTestHelper = IRTestHelperBase<testing::Test>;
diff --git a/src/tint/ir/load_test.cc b/src/tint/ir/load_test.cc
index ad21d13..e14671a 100644
--- a/src/tint/ir/load_test.cc
+++ b/src/tint/ir/load_test.cc
@@ -69,7 +69,7 @@
         {
             Module mod;
             Builder b{mod};
-            b.Load(b.Declare(mod.Types().f32()));
+            b.Load(b.Constant(1_i));
         },
         "");
 }
diff --git a/src/tint/ir/module_test.cc b/src/tint/ir/module_test.cc
index 945e499..457042c 100644
--- a/src/tint/ir/module_test.cc
+++ b/src/tint/ir/module_test.cc
@@ -21,30 +21,35 @@
 
 using namespace tint::number_suffixes;  // NOLINT
 
-using IR_ModuleTest = IRTestHelper;
+class IR_ModuleTest : public IRTestHelper {
+  protected:
+    const type::Pointer* ptr(const type::Type* elem) {
+        return ty.pointer(elem, builtin::AddressSpace::kFunction, builtin::Access::kReadWrite);
+    }
+};
 
 TEST_F(IR_ModuleTest, NameOfUnnamed) {
-    auto* v = mod.values.Create<ir::Var>(mod.Types().i32());
+    auto* v = mod.values.Create<ir::Var>(ptr(ty.i32()));
     EXPECT_FALSE(mod.NameOf(v).IsValid());
 }
 
 TEST_F(IR_ModuleTest, SetName) {
-    auto* v = mod.values.Create<ir::Var>(mod.Types().i32());
+    auto* v = mod.values.Create<ir::Var>(ptr(ty.i32()));
     EXPECT_EQ(mod.SetName(v, "a").Name(), "a");
     EXPECT_EQ(mod.NameOf(v).Name(), "a");
 }
 
 TEST_F(IR_ModuleTest, SetNameRename) {
-    auto* v = mod.values.Create<ir::Var>(mod.Types().i32());
+    auto* v = mod.values.Create<ir::Var>(ptr(ty.i32()));
     EXPECT_EQ(mod.SetName(v, "a").Name(), "a");
     EXPECT_EQ(mod.SetName(v, "b").Name(), "b");
     EXPECT_EQ(mod.NameOf(v).Name(), "b");
 }
 
 TEST_F(IR_ModuleTest, SetNameCollision) {
-    auto* a = mod.values.Create<ir::Var>(mod.Types().i32());
-    auto* b = mod.values.Create<ir::Var>(mod.Types().i32());
-    auto* c = mod.values.Create<ir::Var>(mod.Types().i32());
+    auto* a = mod.values.Create<ir::Var>(ptr(ty.i32()));
+    auto* b = mod.values.Create<ir::Var>(ptr(ty.i32()));
+    auto* c = mod.values.Create<ir::Var>(ptr(ty.i32()));
     EXPECT_EQ(mod.SetName(a, "x").Name(), "x");
     EXPECT_EQ(mod.SetName(b, "x_1").Name(), "x_1");
     EXPECT_EQ(mod.SetName(c, "x").Name(), "x_2");
diff --git a/src/tint/ir/to_program.cc b/src/tint/ir/to_program.cc
index a041ca7..cb0c935 100644
--- a/src/tint/ir/to_program.cc
+++ b/src/tint/ir/to_program.cc
@@ -290,7 +290,7 @@
     /// @return an ast::VariableDeclStatement from @p var
     const ast::VariableDeclStatement* Var(const ir::Var* var) {
         Symbol name = AssignNameTo(var);
-        auto* ptr = var->Type()->As<type::Pointer>();
+        auto* ptr = var->Type();
         auto ty = Type(ptr->StoreType());
         const ast::Expression* init = nullptr;
         if (var->Initializer()) {
diff --git a/src/tint/ir/validate.cc b/src/tint/ir/validate.cc
index 029ed8f..5a5fb70 100644
--- a/src/tint/ir/validate.cc
+++ b/src/tint/ir/validate.cc
@@ -134,7 +134,7 @@
         diagnostics_.add_note(tint::diag::System::IR, note, src);
     }
 
-    std::string Name(const Value* v) { return mod_.NameOf(v).Name(); }
+    // std::string Name(const Value* v) { return mod_.NameOf(v).Name(); }
 
     void CheckRootBlock(const Block* blk) {
         if (!blk) {
@@ -150,10 +150,6 @@
                          std::string("root block: invalid instruction: ") + inst->TypeInfo().name);
                 continue;
             }
-            if (!var->Type()->Is<type::Pointer>()) {
-                AddError(inst, std::string("root block: 'var' ") + Name(var) +
-                                   "type is not a pointer: " + var->Type()->TypeInfo().name);
-            }
         }
     }
 
diff --git a/src/tint/ir/validate_test.cc b/src/tint/ir/validate_test.cc
index 0fab76f..fcb1997 100644
--- a/src/tint/ir/validate_test.cc
+++ b/src/tint/ir/validate_test.cc
@@ -78,33 +78,6 @@
 )");
 }
 
-TEST_F(IR_ValidateTest, RootBlock_VarBadType) {
-    mod.root_block = b.CreateRootBlockIfNeeded();
-    mod.root_block->Append(b.Declare(mod.Types().i32()));
-    auto res = ir::Validate(mod);
-    ASSERT_FALSE(res);
-    EXPECT_EQ(res.Failure().str(),
-              R"(:3:12 error: root block: 'var' type is not a pointer: tint::type::I32
-  %1:i32 = var
-           ^^^
-
-:2:1 note: In block
-%b1 = block {
-^^^^^^^^^^^^^
-  %1:i32 = var
-^^^^^^^^^^^^^^
-}
-^
-
-note: # Disassembly
-# Root block
-%b1 = block {
-  %1:i32 = var
-}
-
-)");
-}
-
 TEST_F(IR_ValidateTest, Function) {
     auto* f = b.CreateFunction("my_func", mod.Types().void_());
     mod.functions.Push(f);
diff --git a/src/tint/ir/var.cc b/src/tint/ir/var.cc
index 8b0225f..4dd00ce 100644
--- a/src/tint/ir/var.cc
+++ b/src/tint/ir/var.cc
@@ -19,7 +19,7 @@
 
 namespace tint::ir {
 
-Var::Var(const type::Type* ty) : type_(ty) {
+Var::Var(const type::Pointer* ty) : type_(ty) {
     TINT_ASSERT(IR, type_ != nullptr);
 
     // Default to no initializer.
diff --git a/src/tint/ir/var.h b/src/tint/ir/var.h
index 3c633cc..b9efa4e 100644
--- a/src/tint/ir/var.h
+++ b/src/tint/ir/var.h
@@ -19,6 +19,7 @@
 #include "src/tint/builtin/address_space.h"
 #include "src/tint/ir/binding_point.h"
 #include "src/tint/ir/operand_instruction.h"
+#include "src/tint/type/pointer.h"
 #include "src/tint/utils/castable.h"
 #include "src/tint/utils/vector.h"
 
@@ -29,11 +30,11 @@
   public:
     /// Constructor
     /// @param type the type of the var
-    explicit Var(const type::Type* type);
+    explicit Var(const type::Pointer* type);
     ~Var() override;
 
     /// @returns the type of the var
-    const type::Type* Type() const override { return type_; }
+    const type::Pointer* Type() const override { return type_; }
 
     /// Sets the var initializer
     /// @param initializer the initializer
@@ -49,7 +50,7 @@
     std::optional<struct BindingPoint> BindingPoint() const { return binding_point_; }
 
   private:
-    const type::Type* type_ = nullptr;
+    const type::Pointer* type_ = nullptr;
     std::optional<struct BindingPoint> binding_point_;
 };
 
diff --git a/src/tint/ir/var_test.cc b/src/tint/ir/var_test.cc
index ebde1bc..5bcb47d 100644
--- a/src/tint/ir/var_test.cc
+++ b/src/tint/ir/var_test.cc
@@ -39,7 +39,8 @@
 TEST_F(IR_VarTest, Initializer_Usage) {
     Module mod;
     Builder b{mod};
-    auto* var = b.Declare(mod.Types().f32());
+    auto* var = b.Declare(
+        ty.pointer(ty.f32(), builtin::AddressSpace::kFunction, builtin::Access::kReadWrite));
     auto* init = b.Constant(1_f);
     var->SetInitializer(init);
 
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir.cc b/src/tint/writer/spirv/ir/generator_impl_ir.cc
index b61dc21..f786c1f 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir.cc
@@ -879,8 +879,7 @@
 
 void GeneratorImplIr::EmitVar(const ir::Var* var) {
     auto id = Value(var);
-    auto* ptr = var->Type()->As<type::Pointer>();
-    TINT_ASSERT(Writer, ptr);
+    auto* ptr = var->Type();
     auto ty = Type(ptr);
 
     switch (ptr->AddressSpace()) {
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_access_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_access_test.cc
index 62dd469..bdc0e27 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_access_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_access_test.cc
@@ -21,7 +21,7 @@
 
 class SpvGeneratorImplTest_Access : public SpvGeneratorImplTest {
   protected:
-    const type::Type* ptr(const type::Type* elem) {
+    const type::Pointer* ptr(const type::Type* elem) {
         return ty.pointer(elem, builtin::AddressSpace::kFunction, builtin::Access::kReadWrite);
     }
 };