Convert the id attribute to expressions.
This CL updates the @id attribute to use expressions instead of
integers.
Bug: tint:1633
Change-Id: I3db9ab39f10a7f50f8d1e418ec508d4e709a24ff
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/106120
Auto-Submit: Dan Sinclair <dsinclair@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
diff --git a/src/tint/resolver/attribute_validation_test.cc b/src/tint/resolver/attribute_validation_test.cc
index 3e092ed..212f594 100644
--- a/src/tint/resolver/attribute_validation_test.cc
+++ b/src/tint/resolver/attribute_validation_test.cc
@@ -1640,6 +1640,41 @@
EXPECT_EQ(r()->error(), R"(12:34 error: 'group' must be an i32 or u32 value)");
}
+using IdTest = ResolverTest;
+
+TEST_F(IdTest, Const_I32) {
+ Override("val", ty.f32(), utils::Vector{Id(1_i)});
+ EXPECT_TRUE(r()->Resolve()) << r()->error();
+}
+
+TEST_F(IdTest, Const_U32) {
+ Override("val", ty.f32(), utils::Vector{Id(1_u)});
+ EXPECT_TRUE(r()->Resolve()) << r()->error();
+}
+
+TEST_F(IdTest, Const_AInt) {
+ Override("val", ty.f32(), utils::Vector{Id(1_a)});
+ EXPECT_TRUE(r()->Resolve()) << r()->error();
+}
+
+TEST_F(IdTest, Negative) {
+ Override("val", ty.f32(), utils::Vector{Id(Source{{12, 34}}, -1_i)});
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), R"(12:34 error: 'id' value must be non-negative)");
+}
+
+TEST_F(IdTest, F32) {
+ Override("val", ty.f32(), utils::Vector{Id(Source{{12, 34}}, 1_f)});
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), R"(12:34 error: 'id' must be an i32 or u32 value)");
+}
+
+TEST_F(IdTest, AFloat) {
+ Override("val", ty.f32(), utils::Vector{Id(Source{{12, 34}}, 1.0_a)});
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), R"(12:34 error: 'id' must be an i32 or u32 value)");
+}
+
} // namespace
} // namespace InterpolateTests
diff --git a/src/tint/resolver/dependency_graph.cc b/src/tint/resolver/dependency_graph.cc
index 514e0cb..4d67023 100644
--- a/src/tint/resolver/dependency_graph.cc
+++ b/src/tint/resolver/dependency_graph.cc
@@ -427,6 +427,10 @@
TraverseExpression(group->expr);
return true;
},
+ [&](const ast::IdAttribute* id) {
+ TraverseExpression(id->expr);
+ return true;
+ },
[&](const ast::StructMemberAlignAttribute* align) {
TraverseExpression(align->expr);
return true;
@@ -445,10 +449,9 @@
return;
}
- if (attr->IsAnyOf<ast::BuiltinAttribute, ast::IdAttribute, ast::InternalAttribute,
- ast::InterpolateAttribute, ast::InvariantAttribute,
- ast::LocationAttribute, ast::StageAttribute, ast::StrideAttribute,
- ast::StructMemberOffsetAttribute>()) {
+ if (attr->IsAnyOf<ast::BuiltinAttribute, ast::InternalAttribute, ast::InterpolateAttribute,
+ ast::InvariantAttribute, ast::LocationAttribute, ast::StageAttribute,
+ ast::StrideAttribute, ast::StructMemberOffsetAttribute>()) {
return;
}
diff --git a/src/tint/resolver/dependency_graph_test.cc b/src/tint/resolver/dependency_graph_test.cc
index 150d65a..138507a 100644
--- a/src/tint/resolver/dependency_graph_test.cc
+++ b/src/tint/resolver/dependency_graph_test.cc
@@ -1291,6 +1291,7 @@
GlobalVar(Sym(), ty.sampler(ast::SamplerKind::kSampler));
GlobalVar(Sym(), ty.i32(), utils::Vector{Binding(V), Group(V)});
+ Override(Sym(), ty.i32(), utils::Vector{Id(V)});
Func(Sym(), utils::Empty, ty.void_(), utils::Empty);
#undef V
diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc
index 9bbe439..56f9246 100644
--- a/src/tint/resolver/resolver.cc
+++ b/src/tint/resolver/resolver.cc
@@ -449,18 +449,24 @@
sem->SetConstructor(rhs);
if (auto* id_attr = ast::GetAttribute<ast::IdAttribute>(v->attributes)) {
- auto* materialize = Materialize(Expression(id_attr->expr));
- if (!materialize) {
+ ExprEvalStageConstraint constraint{sem::EvaluationStage::kConstant, "@id"};
+ TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint);
+
+ auto* materialized = Materialize(Expression(id_attr->expr));
+ if (!materialized) {
return nullptr;
}
- auto* c = materialize->ConstantValue();
- if (!c) {
- // TODO(crbug.com/tint/1633): Handle invalid materialization when expressions are
- // supported.
+ if (!materialized->Type()->IsAnyOf<sem::I32, sem::U32>()) {
+ AddError("'id' must be an i32 or u32 value", id_attr->source);
return nullptr;
}
- auto value = c->As<uint32_t>();
+ auto const_value = materialized->ConstantValue();
+ auto value = const_value->As<AInt>();
+ if (value < 0) {
+ AddError("'id' value must be non-negative", id_attr->source);
+ return nullptr;
+ }
if (value > std::numeric_limits<decltype(OverrideId::value)>::max()) {
AddError("override IDs must be between 0 and " +
std::to_string(std::numeric_limits<decltype(OverrideId::value)>::max()),