Add ast::Variable::BindingPoint

Use this to simplify a bunch of code in semantic::Function.

Change-Id: Ia3f8a270ec576660eab00bcfa4df9a96138bd31e
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/46261
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: James Price <jrprice@google.com>
This commit is contained in:
Ben Clayton 2021-03-29 21:21:35 +00:00 committed by Commit Bot service account
parent af8a8ac3d6
commit a864f24c6f
5 changed files with 87 additions and 67 deletions

View File

@ -45,6 +45,19 @@ Variable::Variable(Variable&&) = default;
Variable::~Variable() = default; Variable::~Variable() = default;
Variable::BindingPoint Variable::binding_point() const {
GroupDecoration* group = nullptr;
BindingDecoration* binding = nullptr;
for (auto* deco : decorations()) {
if (auto* g = deco->As<GroupDecoration>()) {
group = g;
} else if (auto* b = deco->As<BindingDecoration>()) {
binding = b;
}
}
return BindingPoint{group, binding};
}
bool Variable::HasLocationDecoration() const { bool Variable::HasLocationDecoration() const {
for (auto* deco : decorations_) { for (auto* deco : decorations_) {
if (deco->Is<LocationDecoration>()) { if (deco->Is<LocationDecoration>()) {

View File

@ -25,6 +25,8 @@
namespace tint { namespace tint {
namespace ast { namespace ast {
class BindingDecoration;
class GroupDecoration;
class LocationDecoration; class LocationDecoration;
/// A Variable statement. /// A Variable statement.
@ -76,6 +78,18 @@ class LocationDecoration;
/// The storage class for a formal parameter is always StorageClass::kNone. /// The storage class for a formal parameter is always StorageClass::kNone.
class Variable : public Castable<Variable, Node> { class Variable : public Castable<Variable, Node> {
public: public:
/// BindingPoint holds a group and binding decoration.
struct BindingPoint {
/// The `[[group]]` part of the binding point
GroupDecoration* group = nullptr;
/// The `[[binding]]` part of the binding point
BindingDecoration* binding = nullptr;
/// @returns true if the BindingPoint has a valid group and binding
/// decoration.
inline operator bool() const { return group && binding; }
};
/// Create a variable /// Create a variable
/// @param source the variable source /// @param source the variable source
/// @param sym the variable symbol /// @param sym the variable symbol
@ -117,6 +131,9 @@ class Variable : public Castable<Variable, Node> {
/// @returns the decorations attached to this variable /// @returns the decorations attached to this variable
const DecorationList& decorations() const { return decorations_; } const DecorationList& decorations() const { return decorations_; }
/// @returns the binding point information for the variable
BindingPoint binding_point() const;
/// @returns true if the decorations include a LocationDecoration /// @returns true if the decorations include a LocationDecoration
bool HasLocationDecoration() const; bool HasLocationDecoration() const;
/// @returns true if the decorations include a BuiltinDecoration /// @returns true if the decorations include a BuiltinDecoration

View File

@ -107,6 +107,47 @@ TEST_F(VariableTest, WithDecorations) {
EXPECT_EQ(1u, location->value()); EXPECT_EQ(1u, location->value());
} }
TEST_F(VariableTest, BindingPoint) {
auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, nullptr,
DecorationList{
create<BindingDecoration>(2),
create<GroupDecoration>(1),
});
EXPECT_TRUE(var->binding_point());
ASSERT_NE(var->binding_point().binding, nullptr);
ASSERT_NE(var->binding_point().group, nullptr);
EXPECT_EQ(var->binding_point().binding->value(), 2u);
EXPECT_EQ(var->binding_point().group->value(), 1u);
}
TEST_F(VariableTest, BindingPointoDecorations) {
auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, nullptr,
DecorationList{});
EXPECT_FALSE(var->binding_point());
EXPECT_EQ(var->binding_point().group, nullptr);
EXPECT_EQ(var->binding_point().binding, nullptr);
}
TEST_F(VariableTest, BindingPointMissingGroupDecoration) {
auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, nullptr,
DecorationList{
create<BindingDecoration>(2),
});
EXPECT_FALSE(var->binding_point());
ASSERT_NE(var->binding_point().binding, nullptr);
EXPECT_EQ(var->binding_point().binding->value(), 2u);
EXPECT_EQ(var->binding_point().group, nullptr);
}
TEST_F(VariableTest, BindingPointMissingBindingDecoration) {
auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, nullptr,
DecorationList{create<GroupDecoration>(1)});
EXPECT_FALSE(var->binding_point());
ASSERT_NE(var->binding_point().group, nullptr);
EXPECT_EQ(var->binding_point().group->value(), 1u);
EXPECT_EQ(var->binding_point().binding, nullptr);
}
TEST_F(VariableTest, ConstantId) { TEST_F(VariableTest, ConstantId) {
auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, nullptr, auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, nullptr,
DecorationList{ DecorationList{

View File

@ -18,6 +18,7 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "src/ast/variable.h"
#include "src/semantic/call_target.h" #include "src/semantic/call_target.h"
namespace tint { namespace tint {
@ -39,16 +40,9 @@ class Variable;
/// Function holds the semantic information for function nodes. /// Function holds the semantic information for function nodes.
class Function : public Castable<Function, CallTarget> { class Function : public Castable<Function, CallTarget> {
public: public:
/// Information about a binding /// A vector of [Variable*, ast::Variable::BindingPoint] pairs
struct BindingInfo { using VariableBindings =
/// The binding decoration std::vector<std::pair<const Variable*, ast::Variable::BindingPoint>>;
ast::BindingDecoration* binding = nullptr;
/// The group decoration
ast::GroupDecoration* group = nullptr;
};
/// A vector of [Variable*, BindingInfo] pairs
using VariableBindings = std::vector<std::pair<const Variable*, BindingInfo>>;
/// Constructor /// Constructor
/// @param declaration the ast::Function /// @param declaration the ast::Function

View File

@ -38,21 +38,6 @@ ParameterList GetParameters(ast::Function* ast) {
return parameters; return parameters;
} }
std::tuple<ast::BindingDecoration*, ast::GroupDecoration*> GetBindingAndGroup(
const Variable* var) {
ast::BindingDecoration* binding = nullptr;
ast::GroupDecoration* group = nullptr;
for (auto* deco : var->Declaration()->decorations()) {
if (auto* b = deco->As<ast::BindingDecoration>()) {
binding = b;
}
if (auto* s = deco->As<ast::GroupDecoration>()) {
group = s;
}
}
return {binding, group};
}
} // namespace } // namespace
Function::Function(ast::Function* declaration, Function::Function(ast::Function* declaration,
@ -92,14 +77,9 @@ Function::VariableBindings Function::ReferencedUniformVariables() const {
continue; continue;
} }
ast::BindingDecoration* binding = nullptr; if (auto binding_point = var->Declaration()->binding_point()) {
ast::GroupDecoration* group = nullptr; ret.push_back({var, binding_point});
std::tie(binding, group) = GetBindingAndGroup(var);
if (binding == nullptr || group == nullptr) {
continue;
} }
ret.push_back({var, BindingInfo{binding, group}});
} }
return ret; return ret;
} }
@ -112,14 +92,9 @@ Function::VariableBindings Function::ReferencedStorageBufferVariables() const {
continue; continue;
} }
ast::BindingDecoration* binding = nullptr; if (auto binding_point = var->Declaration()->binding_point()) {
ast::GroupDecoration* group = nullptr; ret.push_back({var, binding_point});
std::tie(binding, group) = GetBindingAndGroup(var);
if (binding == nullptr || group == nullptr) {
continue;
} }
ret.push_back({var, BindingInfo{binding, group}});
} }
return ret; return ret;
} }
@ -168,14 +143,9 @@ Function::VariableBindings Function::ReferencedStorageTextureVariables() const {
continue; continue;
} }
ast::BindingDecoration* binding = nullptr; if (auto binding_point = var->Declaration()->binding_point()) {
ast::GroupDecoration* group = nullptr; ret.push_back({var, binding_point});
std::tie(binding, group) = GetBindingAndGroup(var);
if (binding == nullptr || group == nullptr) {
continue;
} }
ret.push_back({var, BindingInfo{binding, group}});
} }
return ret; return ret;
} }
@ -191,14 +161,9 @@ Function::VariableBindings Function::ReferencedDepthTextureVariables() const {
continue; continue;
} }
ast::BindingDecoration* binding = nullptr; if (auto binding_point = var->Declaration()->binding_point()) {
ast::GroupDecoration* group = nullptr; ret.push_back({var, binding_point});
std::tie(binding, group) = GetBindingAndGroup(var);
if (binding == nullptr || group == nullptr) {
continue;
} }
ret.push_back({var, BindingInfo{binding, group}});
} }
return ret; return ret;
} }
@ -239,14 +204,9 @@ Function::VariableBindings Function::ReferencedSamplerVariablesImpl(
continue; continue;
} }
ast::BindingDecoration* binding = nullptr; if (auto binding_point = var->Declaration()->binding_point()) {
ast::GroupDecoration* group = nullptr; ret.push_back({var, binding_point});
std::tie(binding, group) = GetBindingAndGroup(var);
if (binding == nullptr || group == nullptr) {
continue;
} }
ret.push_back({var, BindingInfo{binding, group}});
} }
return ret; return ret;
} }
@ -270,14 +230,9 @@ Function::VariableBindings Function::ReferencedSampledTextureVariablesImpl(
continue; continue;
} }
ast::BindingDecoration* binding = nullptr; if (auto binding_point = var->Declaration()->binding_point()) {
ast::GroupDecoration* group = nullptr; ret.push_back({var, binding_point});
std::tie(binding, group) = GetBindingAndGroup(var);
if (binding == nullptr || group == nullptr) {
continue;
} }
ret.push_back({var, BindingInfo{binding, group}});
} }
return ret; return ret;