Add location into `sem::Parameter`.

This CL adds a `location` value into the `Parameter` sem object.
This will be set if the parameter has an `@location` attribute
applied.

Bug: tint:1633
Change-Id: I55cb5cbda951f70d071ebe1400865b63af1fb20a
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/101065
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc
index 93f0bdc..1eb3b35 100644
--- a/src/tint/resolver/resolver.cc
+++ b/src/tint/resolver/resolver.cc
@@ -716,9 +716,14 @@
         }
     }
 
-    auto* sem = builder_->create<sem::Parameter>(param, index, ty, ast::StorageClass::kNone,
-                                                 ast::Access::kUndefined,
-                                                 sem::ParameterUsage::kNone, binding_point);
+    std::optional<uint32_t> location;
+    if (auto* l = ast::GetAttribute<ast::LocationAttribute>(param->attributes)) {
+        location = l->value;
+    }
+
+    auto* sem = builder_->create<sem::Parameter>(
+        param, index, ty, ast::StorageClass::kNone, ast::Access::kUndefined,
+        sem::ParameterUsage::kNone, binding_point, location);
     builder_->Sem().Add(param, sem);
     return sem;
 }
diff --git a/src/tint/resolver/resolver_test.cc b/src/tint/resolver/resolver_test.cc
index 5f58c4c..523dd89 100644
--- a/src/tint/resolver/resolver_test.cc
+++ b/src/tint/resolver/resolver_test.cc
@@ -773,6 +773,39 @@
     EXPECT_TRUE(func_sem->ReturnType()->Is<sem::Void>());
 }
 
+TEST_F(ResolverTest, Function_Parameters_Locations) {
+    auto* param_a = Param("a", ty.f32(), utils::Vector{Location(3)});
+    auto* param_b = Param("b", ty.u32(), utils::Vector{Builtin(ast::BuiltinValue::kVertexIndex)});
+    auto* param_c = Param("c", ty.u32(), utils::Vector{Location(1)});
+
+    GlobalVar("my_vec", ty.vec4<f32>(), ast::StorageClass::kPrivate);
+    auto* func = Func("my_func",
+                      utils::Vector{
+                          param_a,
+                          param_b,
+                          param_c,
+                      },
+                      ty.vec4<f32>(),
+                      utils::Vector{
+                          Return("my_vec"),
+                      },
+                      utils::Vector{
+                          Stage(ast::PipelineStage::kVertex),
+                      },
+                      utils::Vector{
+                          Builtin(ast::BuiltinValue::kPosition),
+                      });
+
+    EXPECT_TRUE(r()->Resolve()) << r()->error();
+
+    auto* func_sem = Sem().Get(func);
+    ASSERT_NE(func_sem, nullptr);
+    EXPECT_EQ(func_sem->Parameters().Length(), 3u);
+    EXPECT_EQ(3u, func_sem->Parameters()[0]->Location());
+    EXPECT_FALSE(func_sem->Parameters()[1]->Location().has_value());
+    EXPECT_EQ(1u, func_sem->Parameters()[2]->Location());
+}
+
 TEST_F(ResolverTest, Function_RegisterInputOutputVariables) {
     auto* s = Structure("S", utils::Vector{Member("m", ty.u32())});
 
diff --git a/src/tint/sem/variable.cc b/src/tint/sem/variable.cc
index f233053..67e7945 100644
--- a/src/tint/sem/variable.cc
+++ b/src/tint/sem/variable.cc
@@ -73,11 +73,13 @@
                      ast::StorageClass storage_class,
                      ast::Access access,
                      const ParameterUsage usage /* = ParameterUsage::kNone */,
-                     sem::BindingPoint binding_point /* = {} */)
+                     sem::BindingPoint binding_point /* = {} */,
+                     std::optional<uint32_t> location /* = std::nullopt */)
     : Base(declaration, type, EvaluationStage::kRuntime, storage_class, access, nullptr),
       index_(index),
       usage_(usage),
-      binding_point_(binding_point) {}
+      binding_point_(binding_point),
+      location_(location) {}
 
 Parameter::~Parameter() = default;
 
diff --git a/src/tint/sem/variable.h b/src/tint/sem/variable.h
index b511563..a0eb75e 100644
--- a/src/tint/sem/variable.h
+++ b/src/tint/sem/variable.h
@@ -15,6 +15,7 @@
 #ifndef SRC_TINT_SEM_VARIABLE_H_
 #define SRC_TINT_SEM_VARIABLE_H_
 
+#include <optional>
 #include <utility>
 #include <vector>
 
@@ -189,13 +190,15 @@
     /// @param access the variable access control type
     /// @param usage the semantic usage for the parameter
     /// @param binding_point the optional resource binding point of the parameter
+    /// @param location the location value, if set
     Parameter(const ast::Parameter* declaration,
               uint32_t index,
               const sem::Type* type,
               ast::StorageClass storage_class,
               ast::Access access,
               const ParameterUsage usage = ParameterUsage::kNone,
-              sem::BindingPoint binding_point = {});
+              sem::BindingPoint binding_point = {},
+              std::optional<uint32_t> location = std::nullopt);
 
     /// Destructor
     ~Parameter() override;
@@ -222,12 +225,16 @@
     /// @returns the resource binding point for the parameter
     sem::BindingPoint BindingPoint() const { return binding_point_; }
 
+    /// @returns the location value for the parameter, if set
+    std::optional<uint32_t> Location() const { return location_; }
+
   private:
     const uint32_t index_;
     const ParameterUsage usage_;
     CallTarget const* owner_ = nullptr;
     const sem::Node* shadows_ = nullptr;
     const sem::BindingPoint binding_point_;
+    const std::optional<uint32_t> location_;
 };
 
 /// VariableUser holds the semantic information for an identifier expression