diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc index 93f0bdcf63..1eb3b35433 100644 --- a/src/tint/resolver/resolver.cc +++ b/src/tint/resolver/resolver.cc @@ -716,9 +716,14 @@ sem::Parameter* Resolver::Parameter(const ast::Parameter* param, uint32_t index) } } - auto* sem = builder_->create(param, index, ty, ast::StorageClass::kNone, - ast::Access::kUndefined, - sem::ParameterUsage::kNone, binding_point); + std::optional location; + if (auto* l = ast::GetAttribute(param->attributes)) { + location = l->value; + } + + auto* sem = builder_->create( + 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 5f58c4c920..523dd89908 100644 --- a/src/tint/resolver/resolver_test.cc +++ b/src/tint/resolver/resolver_test.cc @@ -773,6 +773,39 @@ TEST_F(ResolverTest, Function_Parameters) { EXPECT_TRUE(func_sem->ReturnType()->Is()); } +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(), ast::StorageClass::kPrivate); + auto* func = Func("my_func", + utils::Vector{ + param_a, + param_b, + param_c, + }, + ty.vec4(), + 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 f2330538fd..67e79455d5 100644 --- a/src/tint/sem/variable.cc +++ b/src/tint/sem/variable.cc @@ -73,11 +73,13 @@ Parameter::Parameter(const ast::Parameter* declaration, ast::StorageClass storage_class, ast::Access access, const ParameterUsage usage /* = ParameterUsage::kNone */, - sem::BindingPoint binding_point /* = {} */) + sem::BindingPoint binding_point /* = {} */, + std::optional 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 b511563cc4..a0eb75e2af 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 #include #include @@ -189,13 +190,15 @@ class Parameter final : public Castable { /// @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 location = std::nullopt); /// Destructor ~Parameter() override; @@ -222,12 +225,16 @@ class Parameter final : public Castable { /// @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 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 location_; }; /// VariableUser holds the semantic information for an identifier expression