[ir] Remove `IOAttributes` from `core/ir/var.h`

Use the version defined in `core/io_attributes.h` instead. This adds
the `color` attribute, which will be needed for framebuffer fetch.

Bug: 340196362
Change-Id: I87aede3ef55a832585efd02f13fe686968d7ab0b
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/196838
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/core/ir/var.h b/src/tint/lang/core/ir/var.h
index 251baeb..3ecb506 100644
--- a/src/tint/lang/core/ir/var.h
+++ b/src/tint/lang/core/ir/var.h
@@ -33,25 +33,12 @@
 #include "src/tint/api/common/binding_point.h"
 #include "src/tint/lang/core/builtin_value.h"
 #include "src/tint/lang/core/interpolation.h"
+#include "src/tint/lang/core/io_attributes.h"
 #include "src/tint/lang/core/ir/operand_instruction.h"
 #include "src/tint/utils/rtti/castable.h"
 
 namespace tint::core::ir {
 
-/// Attributes that can be applied to a variable that will be used for shader IO.
-struct IOAttributes {
-    /// The value of a `@location` attribute.
-    std::optional<uint32_t> location;
-    /// The value of a `@blend_src` attribute.
-    std::optional<uint32_t> blend_src;
-    /// The value of a `@builtin` attribute.
-    std::optional<core::BuiltinValue> builtin;
-    /// The values of a `@interpolate` attribute.
-    std::optional<core::Interpolation> interpolation;
-    /// True if the variable is annotated with `@invariant`.
-    bool invariant = false;
-};
-
 /// A var instruction in the IR.
 class Var final : public Castable<Var, OperandInstruction<1, 1>> {
   public:
diff --git a/src/tint/lang/core/ir/var_test.cc b/src/tint/lang/core/ir/var_test.cc
index 548ba04..d1d8f53 100644
--- a/src/tint/lang/core/ir/var_test.cc
+++ b/src/tint/lang/core/ir/var_test.cc
@@ -75,7 +75,7 @@
     v->SetInitializer(b.Constant(4_f));
     v->SetBindingPoint(1, 2);
     v->SetAttributes(IOAttributes{
-        3, 4, core::BuiltinValue::kFragDepth,
+        3, 4, 5, core::BuiltinValue::kFragDepth,
         Interpolation{core::InterpolationType::kFlat, core::InterpolationSampling::kCentroid},
         true});
 
@@ -103,6 +103,9 @@
     EXPECT_TRUE(attrs.blend_src.has_value());
     EXPECT_EQ(4u, attrs.blend_src.value());
 
+    EXPECT_TRUE(attrs.color.has_value());
+    EXPECT_EQ(5u, attrs.color.value());
+
     EXPECT_TRUE(attrs.builtin.has_value());
     EXPECT_EQ(core::BuiltinValue::kFragDepth, attrs.builtin.value());
 
diff --git a/src/tint/lang/spirv/reader/lower/shader_io.cc b/src/tint/lang/spirv/reader/lower/shader_io.cc
index 0a076f9..7179d8b 100644
--- a/src/tint/lang/spirv/reader/lower/shader_io.cc
+++ b/src/tint/lang/spirv/reader/lower/shader_io.cc
@@ -379,7 +379,7 @@
     /// @param param the parameter
     /// @param attributes the attributes
     void AddEntryPointParameterAttributes(core::ir::FunctionParam* param,
-                                          const core::ir::IOAttributes& attributes) {
+                                          const core::IOAttributes& attributes) {
         if (auto* str = param->Type()->UnwrapPtr()->As<core::type::Struct>()) {
             for (auto* member : str->Members()) {
                 // Use the base variable attributes if not specified directly on the member.
diff --git a/src/tint/lang/spirv/reader/lower/shader_io_test.cc b/src/tint/lang/spirv/reader/lower/shader_io_test.cc
index 24a3d7e..8afe5e2 100644
--- a/src/tint/lang/spirv/reader/lower/shader_io_test.cc
+++ b/src/tint/lang/spirv/reader/lower/shader_io_test.cc
@@ -82,26 +82,26 @@
 TEST_F(SpirvReader_ShaderIOTest, Inputs) {
     auto* front_facing = b.Var("front_facing", ty.ptr(core::AddressSpace::kIn, ty.bool_()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.builtin = core::BuiltinValue::kFrontFacing;
         front_facing->SetAttributes(std::move(attributes));
     }
     auto* position = b.Var("position", ty.ptr(core::AddressSpace::kIn, ty.vec4<f32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.builtin = core::BuiltinValue::kPosition;
         attributes.invariant = true;
         position->SetAttributes(std::move(attributes));
     }
     auto* color1 = b.Var("color1", ty.ptr(core::AddressSpace::kIn, ty.f32()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.location = 0;
         color1->SetAttributes(std::move(attributes));
     }
     auto* color2 = b.Var("color2", ty.ptr(core::AddressSpace::kIn, ty.f32()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.location = 1;
         attributes.interpolation = core::Interpolation{core::InterpolationType::kLinear,
                                                        core::InterpolationSampling::kSample};
@@ -175,26 +175,26 @@
 TEST_F(SpirvReader_ShaderIOTest, Inputs_UsedByHelper) {
     auto* front_facing = b.Var("front_facing", ty.ptr(core::AddressSpace::kIn, ty.bool_()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.builtin = core::BuiltinValue::kFrontFacing;
         front_facing->SetAttributes(std::move(attributes));
     }
     auto* position = b.Var("position", ty.ptr(core::AddressSpace::kIn, ty.vec4<f32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.builtin = core::BuiltinValue::kPosition;
         attributes.invariant = true;
         position->SetAttributes(std::move(attributes));
     }
     auto* color1 = b.Var("color1", ty.ptr(core::AddressSpace::kIn, ty.f32()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.location = 0;
         color1->SetAttributes(std::move(attributes));
     }
     auto* color2 = b.Var("color2", ty.ptr(core::AddressSpace::kIn, ty.f32()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.location = 1;
         attributes.interpolation = core::Interpolation{core::InterpolationType::kLinear,
                                                        core::InterpolationSampling::kSample};
@@ -312,19 +312,19 @@
 TEST_F(SpirvReader_ShaderIOTest, Inputs_UsedEntryPointAndHelper) {
     auto* gid = b.Var("gid", ty.ptr(core::AddressSpace::kIn, ty.vec3<u32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.builtin = core::BuiltinValue::kGlobalInvocationId;
         gid->SetAttributes(std::move(attributes));
     }
     auto* lid = b.Var("lid", ty.ptr(core::AddressSpace::kIn, ty.vec3<u32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.builtin = core::BuiltinValue::kLocalInvocationId;
         lid->SetAttributes(std::move(attributes));
     }
     auto* group_id = b.Var("group_id", ty.ptr(core::AddressSpace::kIn, ty.vec3<u32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.builtin = core::BuiltinValue::kWorkgroupId;
         group_id->SetAttributes(std::move(attributes));
     }
@@ -403,19 +403,19 @@
 TEST_F(SpirvReader_ShaderIOTest, Inputs_UsedEntryPointAndHelper_ForwardReference) {
     auto* gid = b.Var("gid", ty.ptr(core::AddressSpace::kIn, ty.vec3<u32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.builtin = core::BuiltinValue::kGlobalInvocationId;
         gid->SetAttributes(std::move(attributes));
     }
     auto* lid = b.Var("lid", ty.ptr(core::AddressSpace::kIn, ty.vec3<u32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.builtin = core::BuiltinValue::kLocalInvocationId;
         lid->SetAttributes(std::move(attributes));
     }
     auto* group_id = b.Var("group_id", ty.ptr(core::AddressSpace::kIn, ty.vec3<u32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.builtin = core::BuiltinValue::kWorkgroupId;
         group_id->SetAttributes(std::move(attributes));
     }
@@ -495,19 +495,19 @@
 TEST_F(SpirvReader_ShaderIOTest, Inputs_UsedByMultipleEntryPoints) {
     auto* gid = b.Var("gid", ty.ptr(core::AddressSpace::kIn, ty.vec3<u32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.builtin = core::BuiltinValue::kGlobalInvocationId;
         gid->SetAttributes(std::move(attributes));
     }
     auto* lid = b.Var("lid", ty.ptr(core::AddressSpace::kIn, ty.vec3<u32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.builtin = core::BuiltinValue::kLocalInvocationId;
         lid->SetAttributes(std::move(attributes));
     }
     auto* group_id = b.Var("group_id", ty.ptr(core::AddressSpace::kIn, ty.vec3<u32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.builtin = core::BuiltinValue::kWorkgroupId;
         group_id->SetAttributes(std::move(attributes));
     }
@@ -604,7 +604,7 @@
 TEST_F(SpirvReader_ShaderIOTest, Input_LoadVectorElement) {
     auto* lid = b.Var("lid", ty.ptr(core::AddressSpace::kIn, ty.vec3<u32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.builtin = core::BuiltinValue::kLocalInvocationId;
         lid->SetAttributes(std::move(attributes));
     }
@@ -648,7 +648,7 @@
 TEST_F(SpirvReader_ShaderIOTest, Input_AccessChains) {
     auto* lid = b.Var("lid", ty.ptr(core::AddressSpace::kIn, ty.vec3<u32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.builtin = core::BuiltinValue::kLocalInvocationId;
         lid->SetAttributes(std::move(attributes));
     }
@@ -814,7 +814,7 @@
                   });
     auto* colors = b.Var("colors", ty.ptr(core::AddressSpace::kIn, colors_str));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.location = 1u;
         colors->SetAttributes(attributes);
     }
@@ -910,7 +910,7 @@
         });
     auto* colors = b.Var("colors", ty.ptr(core::AddressSpace::kIn, colors_str));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.interpolation = core::Interpolation{core::InterpolationType::kPerspective,
                                                        core::InterpolationSampling::kCentroid};
         colors->SetAttributes(attributes);
@@ -1081,7 +1081,7 @@
 TEST_F(SpirvReader_ShaderIOTest, SingleOutput_Builtin) {
     auto* position = b.Var("position", ty.ptr(core::AddressSpace::kOut, ty.vec4<f32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.builtin = core::BuiltinValue::kPosition;
         position->SetAttributes(std::move(attributes));
     }
@@ -1135,7 +1135,7 @@
 TEST_F(SpirvReader_ShaderIOTest, SingleOutput_Builtin_WithInvariant) {
     auto* position = b.Var("position", ty.ptr(core::AddressSpace::kOut, ty.vec4<f32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.builtin = core::BuiltinValue::kPosition;
         attributes.invariant = true;
         position->SetAttributes(std::move(attributes));
@@ -1190,7 +1190,7 @@
 TEST_F(SpirvReader_ShaderIOTest, SingleOutput_Location) {
     auto* color = b.Var("color", ty.ptr(core::AddressSpace::kOut, ty.vec4<f32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.location = 1u;
         color->SetAttributes(std::move(attributes));
     }
@@ -1244,7 +1244,7 @@
 TEST_F(SpirvReader_ShaderIOTest, SingleOutput_Location_WithInterpolation) {
     auto* color = b.Var("color", ty.ptr(core::AddressSpace::kOut, ty.vec4<f32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.location = 1u;
         attributes.interpolation = core::Interpolation{core::InterpolationType::kPerspective,
                                                        core::InterpolationSampling::kCentroid};
@@ -1300,20 +1300,20 @@
 TEST_F(SpirvReader_ShaderIOTest, MultipleOutputs) {
     auto* position = b.Var("position", ty.ptr(core::AddressSpace::kOut, ty.vec4<f32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.builtin = core::BuiltinValue::kPosition;
         attributes.invariant = true;
         position->SetAttributes(std::move(attributes));
     }
     auto* color1 = b.Var("color1", ty.ptr(core::AddressSpace::kOut, ty.vec4<f32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.location = 1u;
         color1->SetAttributes(std::move(attributes));
     }
     auto* color2 = b.Var("color2", ty.ptr(core::AddressSpace::kOut, ty.vec4<f32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.location = 1u;
         attributes.interpolation = core::Interpolation{core::InterpolationType::kPerspective,
                                                        core::InterpolationSampling::kCentroid};
@@ -1542,7 +1542,7 @@
     auto* builtins = b.Var("builtins", ty.ptr(core::AddressSpace::kOut, builtin_str));
     auto* colors = b.Var("colors", ty.ptr(core::AddressSpace::kOut, colors_str));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.location = 1u;
         colors->SetAttributes(attributes);
     }
@@ -1666,7 +1666,7 @@
     auto* builtins = b.Var("builtins", ty.ptr(core::AddressSpace::kOut, builtin_str));
     auto* colors = b.Var("colors", ty.ptr(core::AddressSpace::kOut, colors_str));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.interpolation = core::Interpolation{core::InterpolationType::kPerspective,
                                                        core::InterpolationSampling::kCentroid};
         colors->SetAttributes(attributes);
@@ -1767,20 +1767,20 @@
 TEST_F(SpirvReader_ShaderIOTest, Outputs_UsedByMultipleEntryPoints) {
     auto* position = b.Var("position", ty.ptr(core::AddressSpace::kOut, ty.vec4<f32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.builtin = core::BuiltinValue::kPosition;
         attributes.invariant = true;
         position->SetAttributes(std::move(attributes));
     }
     auto* color1 = b.Var("color1", ty.ptr(core::AddressSpace::kOut, ty.vec4<f32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.location = 1u;
         color1->SetAttributes(std::move(attributes));
     }
     auto* color2 = b.Var("color2", ty.ptr(core::AddressSpace::kOut, ty.vec4<f32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.location = 1u;
         attributes.interpolation = core::Interpolation{core::InterpolationType::kPerspective,
                                                        core::InterpolationSampling::kCentroid};
@@ -1912,7 +1912,7 @@
 TEST_F(SpirvReader_ShaderIOTest, Output_LoadAndStore) {
     auto* color = b.Var("color", ty.ptr(core::AddressSpace::kOut, ty.vec4<f32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.location = 1u;
         color->SetAttributes(std::move(attributes));
     }
@@ -1975,7 +1975,7 @@
 TEST_F(SpirvReader_ShaderIOTest, Output_LoadVectorElementAndStoreVectorElement) {
     auto* color = b.Var("color", ty.ptr(core::AddressSpace::kOut, ty.vec4<f32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.location = 1u;
         color->SetAttributes(std::move(attributes));
     }
@@ -2038,7 +2038,7 @@
 TEST_F(SpirvReader_ShaderIOTest, Output_AccessChain) {
     auto* color = b.Var("color", ty.ptr(core::AddressSpace::kOut, ty.vec4<f32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.location = 1u;
         color->SetAttributes(std::move(attributes));
     }
@@ -2104,26 +2104,26 @@
 TEST_F(SpirvReader_ShaderIOTest, Inputs_And_Outputs) {
     auto* position = b.Var("position", ty.ptr(core::AddressSpace::kIn, ty.vec4<f32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.builtin = core::BuiltinValue::kPosition;
         attributes.invariant = true;
         position->SetAttributes(std::move(attributes));
     }
     auto* color_in = b.Var("color_in", ty.ptr(core::AddressSpace::kIn, ty.vec4<f32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.location = 0;
         color_in->SetAttributes(std::move(attributes));
     }
     auto* color_out_1 = b.Var("color_out_1", ty.ptr(core::AddressSpace::kOut, ty.vec4<f32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.location = 1;
         color_out_1->SetAttributes(std::move(attributes));
     }
     auto* color_out_2 = b.Var("color_out_2", ty.ptr(core::AddressSpace::kOut, ty.vec4<f32>()));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.location = 2;
         color_out_2->SetAttributes(std::move(attributes));
     }
@@ -2200,13 +2200,13 @@
     auto* arr = ty.array<u32, 1>();
     auto* mask_in = b.Var("mask_in", ty.ptr(core::AddressSpace::kIn, arr));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.builtin = core::BuiltinValue::kSampleMask;
         mask_in->SetAttributes(std::move(attributes));
     }
     auto* mask_out = b.Var("mask_out", ty.ptr(core::AddressSpace::kOut, arr));
     {
-        core::ir::IOAttributes attributes;
+        core::IOAttributes attributes;
         attributes.builtin = core::BuiltinValue::kSampleMask;
         mask_out->SetAttributes(std::move(attributes));
     }
diff --git a/src/tint/lang/spirv/reader/parser/parser.cc b/src/tint/lang/spirv/reader/parser/parser.cc
index ce7e223..c0e08de 100644
--- a/src/tint/lang/spirv/reader/parser/parser.cc
+++ b/src/tint/lang/spirv/reader/parser/parser.cc
@@ -603,7 +603,7 @@
         std::optional<uint32_t> group;
         std::optional<uint32_t> binding;
         core::Access access_mode = core::Access::kUndefined;
-        core::ir::IOAttributes io_attributes;
+        core::IOAttributes io_attributes;
         auto interpolation = [&]() -> core::Interpolation& {
             // Create the interpolation field with the default values on first call.
             if (!io_attributes.interpolation.has_value()) {
diff --git a/src/tint/lang/spirv/writer/printer/printer.cc b/src/tint/lang/spirv/writer/printer/printer.cc
index 2a3df4d..a827c98 100644
--- a/src/tint/lang/spirv/writer/printer/printer.cc
+++ b/src/tint/lang/spirv/writer/printer/printer.cc
@@ -2008,7 +2008,7 @@
     /// @param attrs the shader IO attrs
     /// @param addrspace the address of the variable
     void EmitIOAttributes(uint32_t id,
-                          const core::ir::IOAttributes& attrs,
+                          const core::IOAttributes& attrs,
                           core::AddressSpace addrspace) {
         if (attrs.location) {
             module_.PushAnnot(spv::Op::OpDecorate,
diff --git a/src/tint/lang/spirv/writer/raise/shader_io.cc b/src/tint/lang/spirv/writer/raise/shader_io.cc
index 9e6bc0c..c418877 100644
--- a/src/tint/lang/spirv/writer/raise/shader_io.cc
+++ b/src/tint/lang/spirv/writer/raise/shader_io.cc
@@ -126,9 +126,10 @@
             // Create an IO variable and add it to the root block.
             auto* ptr = ty.ptr(addrspace, store_type, access);
             auto* var = b.Var(name.str(), ptr);
-            var->SetAttributes(core::ir::IOAttributes{
+            var->SetAttributes(core::IOAttributes{
                 io.attributes.location,
                 io.attributes.blend_src,
+                io.attributes.color,
                 io.attributes.builtin,
                 io.attributes.interpolation,
                 io.attributes.invariant,