tint/resolver: Materialize array index expression
Bug: tint:1504
Change-Id: Ib14f4aa8ed7ca9d4bc4cdf6f4acdfa7eec03b716
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/91961
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
diff --git a/src/tint/resolver/array_accessor_test.cc b/src/tint/resolver/array_accessor_test.cc
index 9323b23..d9ef10e 100644
--- a/src/tint/resolver/array_accessor_test.cc
+++ b/src/tint/resolver/array_accessor_test.cc
@@ -156,19 +156,36 @@
EXPECT_TRUE(ref->StoreType()->Is<sem::F32>());
}
-TEST_F(ResolverIndexAccessorTest, Array) {
- auto* idx = Expr(2_i);
+TEST_F(ResolverIndexAccessorTest, Array_Literal_i32) {
Global("my_var", ty.array<f32, 3>(), ast::StorageClass::kPrivate);
-
- auto* acc = IndexAccessor("my_var", idx);
+ auto* acc = IndexAccessor("my_var", 2_i);
WrapInFunction(acc);
-
EXPECT_TRUE(r()->Resolve()) << r()->error();
-
ASSERT_NE(TypeOf(acc), nullptr);
- ASSERT_TRUE(TypeOf(acc)->Is<sem::Reference>());
-
auto* ref = TypeOf(acc)->As<sem::Reference>();
+ ASSERT_NE(ref, nullptr);
+ EXPECT_TRUE(ref->StoreType()->Is<sem::F32>());
+}
+
+TEST_F(ResolverIndexAccessorTest, Array_Literal_u32) {
+ Global("my_var", ty.array<f32, 3>(), ast::StorageClass::kPrivate);
+ auto* acc = IndexAccessor("my_var", 2_u);
+ WrapInFunction(acc);
+ EXPECT_TRUE(r()->Resolve()) << r()->error();
+ ASSERT_NE(TypeOf(acc), nullptr);
+ auto* ref = TypeOf(acc)->As<sem::Reference>();
+ ASSERT_NE(ref, nullptr);
+ EXPECT_TRUE(ref->StoreType()->Is<sem::F32>());
+}
+
+TEST_F(ResolverIndexAccessorTest, Array_Literal_AInt) {
+ Global("my_var", ty.array<f32, 3>(), ast::StorageClass::kPrivate);
+ auto* acc = IndexAccessor("my_var", 2_a);
+ WrapInFunction(acc);
+ EXPECT_TRUE(r()->Resolve()) << r()->error();
+ ASSERT_NE(TypeOf(acc), nullptr);
+ auto* ref = TypeOf(acc)->As<sem::Reference>();
+ ASSERT_NE(ref, nullptr);
EXPECT_TRUE(ref->StoreType()->Is<sem::F32>());
}
@@ -249,7 +266,7 @@
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
-TEST_F(ResolverIndexAccessorTest, EXpr_Deref_FuncGoodParent) {
+TEST_F(ResolverIndexAccessorTest, Expr_Deref_FuncGoodParent) {
// fn func(p: ptr<function, vec4<f32>>) -> f32 {
// let idx: u32 = u32();
// let x: f32 = (*p)[idx];
@@ -265,7 +282,7 @@
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
-TEST_F(ResolverIndexAccessorTest, EXpr_Deref_FuncBadParent) {
+TEST_F(ResolverIndexAccessorTest, Expr_Deref_FuncBadParent) {
// fn func(p: ptr<function, vec4<f32>>) -> f32 {
// let idx: u32 = u32();
// let x: f32 = *p[idx];
diff --git a/src/tint/resolver/materialize_test.cc b/src/tint/resolver/materialize_test.cc
index 8f4451e..774d5d6 100644
--- a/src/tint/resolver/materialize_test.cc
+++ b/src/tint/resolver/materialize_test.cc
@@ -566,16 +566,16 @@
// let a = abstract_expr;
kLet,
- // min(abstract_expr, abstract_expr);
+ // min(abstract_expr, abstract_expr)
kBuiltinArg,
- // bitcast<f32>(abstract_expr);
+ // bitcast<f32>(abstract_expr)
kBitcastF32Arg,
- // bitcast<vec3<f32>>(abstract_expr);
+ // bitcast<vec3<f32>>(abstract_expr)
kBitcastVec3F32Arg,
- // array<i32, abstract_expr>();
+ // array<i32, abstract_expr>()
kArrayLength,
// switch (abstract_expr) {
@@ -587,7 +587,10 @@
// @workgroup_size(abstract_expr)
// @stage(compute)
// fn f() {}
- kWorkgroupSize
+ kWorkgroupSize,
+
+ // arr[abstract_expr]
+ kIndex,
};
static std::ostream& operator<<(std::ostream& o, Method m) {
@@ -608,6 +611,8 @@
return o << "switch";
case Method::kWorkgroupSize:
return o << "workgroup-size";
+ case Method::kIndex:
+ return o << "index";
}
return o << "<unknown>";
}
@@ -692,6 +697,10 @@
Func("f", {}, ty.void_(), {},
{WorkgroupSize(abstract_expr()), Stage(ast::PipelineStage::kCompute)});
break;
+ case Method::kIndex:
+ Global("arr", ty.array<i32, 4>(), ast::StorageClass::kPrivate);
+ WrapInFunction(IndexAccessor("arr", abstract_expr()));
+ break;
}
auto check_types_and_values = [&](const sem::Expression* expr) {
@@ -756,6 +765,14 @@
Method::kBitcastF32Arg,
};
+/// Methods that support abstract-integer materialization
+/// Note: Doesn't contain kWorkgroupSize as @workgroup_size has tighter constraints on the range of
+/// allowed integer values.
+constexpr Method kAIntMethods[] = {
+ Method::kSwitch,
+ Method::kIndex,
+};
+
/// Methods that support vector materialization
constexpr Method kVectorMethods[] = {
Method::kLet,
@@ -826,12 +843,13 @@
Types<f32M, AFloatM>(AFloat(-kSubnormalF32), -kSubnormalF32), //
})));
-INSTANTIATE_TEST_SUITE_P(MaterializeSwitch,
+INSTANTIATE_TEST_SUITE_P(MaterializeAInt,
MaterializeAbstractNumericToDefaultType,
testing::Combine(testing::Values(Expectation::kMaterialize),
- testing::Values(Method::kSwitch),
+ testing::ValuesIn(kAIntMethods),
testing::ValuesIn(std::vector<Data>{
Types<i32, AInt>(0_a, 0.0), //
+ Types<i32, AInt>(10_a, 10.0), //
Types<i32, AInt>(AInt(kHighestI32), kHighestI32), //
Types<i32, AInt>(AInt(kLowestI32), kLowestI32), //
})));
@@ -878,10 +896,10 @@
Types<f32M, AFloatM>(0.0_a, -kTooBigF32), //
})));
-INSTANTIATE_TEST_SUITE_P(SwitchValueCannotBeRepresented,
+INSTANTIATE_TEST_SUITE_P(AIntValueCannotBeRepresented,
MaterializeAbstractNumericToDefaultType,
testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented),
- testing::Values(Method::kSwitch),
+ testing::ValuesIn(kAIntMethods),
testing::ValuesIn(std::vector<Data>{
Types<i32, AInt>(0_a, kHighestI32 + 1), //
Types<i32, AInt>(0_a, kLowestI32 - 1), //
diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc
index c964d8a..04d7b5d 100644
--- a/src/tint/resolver/resolver.cc
+++ b/src/tint/resolver/resolver.cc
@@ -1205,7 +1205,10 @@
}
sem::Expression* Resolver::IndexAccessor(const ast::IndexAccessorExpression* expr) {
- auto* idx = sem_.Get(expr->index);
+ auto* idx = Materialize(sem_.Get(expr->index));
+ if (!idx) {
+ return nullptr;
+ }
auto* obj = sem_.Get(expr->object);
auto* obj_raw_ty = obj->Type();
auto* obj_ty = obj_raw_ty->UnwrapRef();