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>
diff --git a/src/ast/variable.cc b/src/ast/variable.cc
index cab6350..25a11f9 100644
--- a/src/ast/variable.cc
+++ b/src/ast/variable.cc
@@ -45,6 +45,19 @@
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 {
for (auto* deco : decorations_) {
if (deco->Is<LocationDecoration>()) {
diff --git a/src/ast/variable.h b/src/ast/variable.h
index f5f37cb..5f809e8 100644
--- a/src/ast/variable.h
+++ b/src/ast/variable.h
@@ -25,6 +25,8 @@
namespace tint {
namespace ast {
+class BindingDecoration;
+class GroupDecoration;
class LocationDecoration;
/// A Variable statement.
@@ -76,6 +78,18 @@
/// The storage class for a formal parameter is always StorageClass::kNone.
class Variable : public Castable<Variable, Node> {
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
/// @param source the variable source
/// @param sym the variable symbol
@@ -117,6 +131,9 @@
/// @returns the decorations attached to this variable
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
bool HasLocationDecoration() const;
/// @returns true if the decorations include a BuiltinDecoration
diff --git a/src/ast/variable_test.cc b/src/ast/variable_test.cc
index 2651f1a..258f988 100644
--- a/src/ast/variable_test.cc
+++ b/src/ast/variable_test.cc
@@ -107,6 +107,47 @@
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) {
auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, nullptr,
DecorationList{
diff --git a/src/semantic/function.h b/src/semantic/function.h
index fbb5934..efc6fbc 100644
--- a/src/semantic/function.h
+++ b/src/semantic/function.h
@@ -18,6 +18,7 @@
#include <utility>
#include <vector>
+#include "src/ast/variable.h"
#include "src/semantic/call_target.h"
namespace tint {
@@ -39,16 +40,9 @@
/// Function holds the semantic information for function nodes.
class Function : public Castable<Function, CallTarget> {
public:
- /// Information about a binding
- struct BindingInfo {
- /// The binding decoration
- 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>>;
+ /// A vector of [Variable*, ast::Variable::BindingPoint] pairs
+ using VariableBindings =
+ std::vector<std::pair<const Variable*, ast::Variable::BindingPoint>>;
/// Constructor
/// @param declaration the ast::Function
diff --git a/src/semantic/sem_function.cc b/src/semantic/sem_function.cc
index 8e4dcbd..dab7f1c 100644
--- a/src/semantic/sem_function.cc
+++ b/src/semantic/sem_function.cc
@@ -38,21 +38,6 @@
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
Function::Function(ast::Function* declaration,
@@ -92,14 +77,9 @@
continue;
}
- ast::BindingDecoration* binding = nullptr;
- ast::GroupDecoration* group = nullptr;
- std::tie(binding, group) = GetBindingAndGroup(var);
- if (binding == nullptr || group == nullptr) {
- continue;
+ if (auto binding_point = var->Declaration()->binding_point()) {
+ ret.push_back({var, binding_point});
}
-
- ret.push_back({var, BindingInfo{binding, group}});
}
return ret;
}
@@ -112,14 +92,9 @@
continue;
}
- ast::BindingDecoration* binding = nullptr;
- ast::GroupDecoration* group = nullptr;
- std::tie(binding, group) = GetBindingAndGroup(var);
- if (binding == nullptr || group == nullptr) {
- continue;
+ if (auto binding_point = var->Declaration()->binding_point()) {
+ ret.push_back({var, binding_point});
}
-
- ret.push_back({var, BindingInfo{binding, group}});
}
return ret;
}
@@ -168,14 +143,9 @@
continue;
}
- ast::BindingDecoration* binding = nullptr;
- ast::GroupDecoration* group = nullptr;
- std::tie(binding, group) = GetBindingAndGroup(var);
- if (binding == nullptr || group == nullptr) {
- continue;
+ if (auto binding_point = var->Declaration()->binding_point()) {
+ ret.push_back({var, binding_point});
}
-
- ret.push_back({var, BindingInfo{binding, group}});
}
return ret;
}
@@ -191,14 +161,9 @@
continue;
}
- ast::BindingDecoration* binding = nullptr;
- ast::GroupDecoration* group = nullptr;
- std::tie(binding, group) = GetBindingAndGroup(var);
- if (binding == nullptr || group == nullptr) {
- continue;
+ if (auto binding_point = var->Declaration()->binding_point()) {
+ ret.push_back({var, binding_point});
}
-
- ret.push_back({var, BindingInfo{binding, group}});
}
return ret;
}
@@ -239,14 +204,9 @@
continue;
}
- ast::BindingDecoration* binding = nullptr;
- ast::GroupDecoration* group = nullptr;
- std::tie(binding, group) = GetBindingAndGroup(var);
- if (binding == nullptr || group == nullptr) {
- continue;
+ if (auto binding_point = var->Declaration()->binding_point()) {
+ ret.push_back({var, binding_point});
}
-
- ret.push_back({var, BindingInfo{binding, group}});
}
return ret;
}
@@ -270,14 +230,9 @@
continue;
}
- ast::BindingDecoration* binding = nullptr;
- ast::GroupDecoration* group = nullptr;
- std::tie(binding, group) = GetBindingAndGroup(var);
- if (binding == nullptr || group == nullptr) {
- continue;
+ if (auto binding_point = var->Declaration()->binding_point()) {
+ ret.push_back({var, binding_point});
}
-
- ret.push_back({var, BindingInfo{binding, group}});
}
return ret;