tint/resolver: Materialize array size expression

Bug: tint:1504
Change-Id: If67228f18b26f718689f641beae95d281baf9c0c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/91962
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
Ben Clayton 2022-05-31 18:11:34 +00:00 committed by Dawn LUCI CQ
parent b1f9f9fd8e
commit 649d3d9602
3 changed files with 48 additions and 15 deletions

View File

@ -766,8 +766,8 @@ constexpr Method kScalarMethods[] = {
};
/// Methods that support abstract-integer materialization
/// Note: Doesn't contain kWorkgroupSize as @workgroup_size has tighter constraints on the range of
/// allowed integer values.
/// Note: Doesn't contain kWorkgroupSize or kArrayLength as they have tighter constraints on the
/// range of allowed integer values.
constexpr Method kAIntMethods[] = {
Method::kSwitch,
Method::kIndex,
@ -854,6 +854,18 @@ INSTANTIATE_TEST_SUITE_P(MaterializeAInt,
Types<i32, AInt>(AInt(kLowestI32), kLowestI32), //
})));
INSTANTIATE_TEST_SUITE_P(
MaterializeArrayLength,
MaterializeAbstractNumericToDefaultType,
testing::Combine(testing::Values(Expectation::kMaterialize),
testing::Values(Method::kArrayLength),
testing::ValuesIn(std::vector<Data>{
Types<i32, AInt>(1_a, 1.0), //
Types<i32, AInt>(10_a, 10.0), //
Types<i32, AInt>(1000_a, 1000.0), //
// Note: kHighestI32 cannot be used due to max-byte-size validation
})));
INSTANTIATE_TEST_SUITE_P(MaterializeWorkgroupSize,
MaterializeAbstractNumericToDefaultType,
testing::Combine(testing::Values(Expectation::kMaterialize),
@ -914,6 +926,14 @@ INSTANTIATE_TEST_SUITE_P(WorkgroupSizeValueCannotBeRepresented,
Types<i32, AInt>(0_a, kLowestI32 - 1), //
})));
INSTANTIATE_TEST_SUITE_P(ArrayLengthValueCannotBeRepresented,
MaterializeAbstractNumericToDefaultType,
testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented),
testing::Values(Method::kArrayLength),
testing::ValuesIn(std::vector<Data>{
Types<i32, AInt>(0_a, kHighestI32 + 1), //
})));
} // namespace materialize_abstract_numeric_to_default_type
} // namespace

View File

@ -2030,7 +2030,7 @@ sem::Array* Resolver::Array(const ast::Array* arr) {
// sem::Array uses a size of 0 for a runtime-sized array.
uint32_t count = 0;
if (auto* count_expr = arr->count) {
auto* count_sem = Expression(count_expr);
const auto* count_sem = Materialize(Expression(count_expr));
if (!count_sem) {
return nullptr;
}

View File

@ -73,7 +73,7 @@ TEST_F(ResolverTypeValidationTest, VariableDeclNoConstructor_Pass) {
ASSERT_NE(TypeOf(rhs), nullptr);
}
TEST_F(ResolverTypeValidationTest, GlobalConstantNoConstructor_Pass) {
TEST_F(ResolverTypeValidationTest, GlobalOverrideNoConstructor_Pass) {
// @id(0) override a :i32;
Override(Source{{12, 34}}, "a", ty.i32(), nullptr, ast::AttributeList{Id(0)});
@ -87,8 +87,8 @@ TEST_F(ResolverTypeValidationTest, GlobalVariableWithStorageClass_Pass) {
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverTypeValidationTest, GlobalConstantWithStorageClass_Fail) {
// const<private> global_var: f32;
TEST_F(ResolverTypeValidationTest, GlobalLetWithStorageClass_Fail) {
// let<private> global_var: f32;
AST().AddGlobalVariable(create<ast::Variable>(
Source{{12, 34}}, Symbols().Register("global_var"), ast::StorageClass::kPrivate,
ast::Access::kUndefined, ty.f32(), true, false, Expr(1.23_f), ast::AttributeList{}));
@ -188,6 +188,12 @@ TEST_F(ResolverTypeValidationTest, RedeclaredIdentifierDifferentFunctions_Pass)
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverTypeValidationTest, ArraySize_AIntLiteral_Pass) {
// var<private> a : array<f32, 4>;
Global("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 4_a)), ast::StorageClass::kPrivate);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverTypeValidationTest, ArraySize_UnsignedLiteral_Pass) {
// var<private> a : array<f32, 4u>;
Global("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 4_u)), ast::StorageClass::kPrivate);
@ -200,7 +206,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_SignedLiteral_Pass) {
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverTypeValidationTest, ArraySize_UnsignedConstant_Pass) {
TEST_F(ResolverTypeValidationTest, ArraySize_UnsignedLet_Pass) {
// let size = 4u;
// var<private> a : array<f32, size>;
GlobalConst("size", nullptr, Expr(4_u));
@ -208,7 +214,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_UnsignedConstant_Pass) {
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverTypeValidationTest, ArraySize_SignedConstant_Pass) {
TEST_F(ResolverTypeValidationTest, ArraySize_SignedLet_Pass) {
// let size = 4i;
// var<private> a : array<f32, size>;
GlobalConst("size", nullptr, Expr(4_i));
@ -216,6 +222,13 @@ TEST_F(ResolverTypeValidationTest, ArraySize_SignedConstant_Pass) {
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverTypeValidationTest, ArraySize_AIntLiteral_Zero) {
// var<private> a : array<f32, 0>;
Global("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 0_a)), ast::StorageClass::kPrivate);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: array size must be at least 1");
}
TEST_F(ResolverTypeValidationTest, ArraySize_UnsignedLiteral_Zero) {
// var<private> a : array<f32, 0u>;
Global("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, 0_u)), ast::StorageClass::kPrivate);
@ -237,7 +250,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_SignedLiteral_Negative) {
EXPECT_EQ(r()->error(), "12:34 error: array size must be at least 1");
}
TEST_F(ResolverTypeValidationTest, ArraySize_UnsignedConstant_Zero) {
TEST_F(ResolverTypeValidationTest, ArraySize_UnsignedLet_Zero) {
// let size = 0u;
// var<private> a : array<f32, size>;
GlobalConst("size", nullptr, Expr(0_u));
@ -246,7 +259,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_UnsignedConstant_Zero) {
EXPECT_EQ(r()->error(), "12:34 error: array size must be at least 1");
}
TEST_F(ResolverTypeValidationTest, ArraySize_SignedConstant_Zero) {
TEST_F(ResolverTypeValidationTest, ArraySize_SignedLet_Zero) {
// let size = 0i;
// var<private> a : array<f32, size>;
GlobalConst("size", nullptr, Expr(0_i));
@ -255,7 +268,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_SignedConstant_Zero) {
EXPECT_EQ(r()->error(), "12:34 error: array size must be at least 1");
}
TEST_F(ResolverTypeValidationTest, ArraySize_SignedConstant_Negative) {
TEST_F(ResolverTypeValidationTest, ArraySize_SignedLet_Negative) {
// let size = -10i;
// var<private> a : array<f32, size>;
GlobalConst("size", nullptr, Expr(-10_i));
@ -279,7 +292,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_IVecLiteral) {
EXPECT_EQ(r()->error(), "12:34 error: array size must be integer scalar");
}
TEST_F(ResolverTypeValidationTest, ArraySize_FloatConstant) {
TEST_F(ResolverTypeValidationTest, ArraySize_FloatLet) {
// let size = 10.0;
// var<private> a : array<f32, size>;
GlobalConst("size", nullptr, Expr(10_f));
@ -288,7 +301,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_FloatConstant) {
EXPECT_EQ(r()->error(), "12:34 error: array size must be integer scalar");
}
TEST_F(ResolverTypeValidationTest, ArraySize_IVecConstant) {
TEST_F(ResolverTypeValidationTest, ArraySize_IVecLet) {
// let size = vec2<i32>(100, 100);
// var<private> a : array<f32, size>;
GlobalConst("size", nullptr, Construct(ty.vec2<i32>(), 100_i, 100_i));
@ -315,7 +328,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_TooBig_ExplicitStride) {
"is 0x100000000");
}
TEST_F(ResolverTypeValidationTest, ArraySize_OverridableConstant) {
TEST_F(ResolverTypeValidationTest, ArraySize_Overridable) {
// override size = 10i;
// var<private> a : array<f32, size>;
Override("size", nullptr, Expr(10_i));
@ -333,7 +346,7 @@ TEST_F(ResolverTypeValidationTest, ArraySize_ModuleVar) {
EXPECT_EQ(r()->error(), "12:34 error: array size identifier must be a module-scope constant");
}
TEST_F(ResolverTypeValidationTest, ArraySize_FunctionConstant) {
TEST_F(ResolverTypeValidationTest, ArraySize_FunctionLet) {
// {
// let size = 10;
// var a : array<f32, size>;