tint/sem: Support arrays for sem::Constant

https://github.com/gpuweb/gpuweb/issues/3056 proposes that creation-time
constant expressions should support arrays. We have verbal agreement to
update to spec to support const arrays.

Bug: tint:1580
Change-Id: If460f729384d700a1c2149c5b7dbe8613a960184
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/94330
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
Ben Clayton 2022-06-24 15:28:28 +00:00 committed by Dawn LUCI CQ
parent c174692187
commit 3c054304a8
29 changed files with 2479 additions and 2048 deletions

View File

@ -178,14 +178,13 @@ sem::Constant Resolver::EvaluateConstantValue(const ast::CallExpression* call,
const sem::Type* ty) { const sem::Type* ty) {
uint32_t num_elems = 0; uint32_t num_elems = 0;
auto* el_ty = sem::Type::DeepestElementOf(ty, &num_elems); auto* el_ty = sem::Type::DeepestElementOf(ty, &num_elems);
if (!el_ty) { if (!el_ty || num_elems == 0) {
return {}; return {};
} }
// ElementOf() will also return the element type of array, which we do not support. // Note: we are building constant values for array types. The working group as verbally agreed
if (ty->Is<sem::Array>()) { // to support constant expression arrays, but this is not (yet) part of the spec.
return sem::Constant{}; // See: https://github.com/gpuweb/gpuweb/issues/3056
}
// For zero value init, return 0s // For zero value init, return 0s
if (call->args.empty()) { if (call->args.empty()) {

View File

@ -25,6 +25,10 @@ namespace {
using ResolverConstantsTest = ResolverTest; using ResolverConstantsTest = ResolverTest;
////////////////////////////////////////////////////////////////////////////////////////////////////
// Construction
////////////////////////////////////////////////////////////////////////////////////////////////////
TEST_F(ResolverConstantsTest, Scalar_i32) { TEST_F(ResolverConstantsTest, Scalar_i32) {
auto* expr = Expr(99_i); auto* expr = Expr(99_i);
WrapInFunction(expr); WrapInFunction(expr);
@ -32,7 +36,7 @@ TEST_F(ResolverConstantsTest, Scalar_i32) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_TRUE(sem->Type()->Is<sem::I32>()); EXPECT_TRUE(sem->Type()->Is<sem::I32>());
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type()); EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_EQ(sem->ConstantValue().ElementType(), sem->Type()); EXPECT_EQ(sem->ConstantValue().ElementType(), sem->Type());
@ -47,7 +51,7 @@ TEST_F(ResolverConstantsTest, Scalar_u32) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_TRUE(sem->Type()->Is<sem::U32>()); EXPECT_TRUE(sem->Type()->Is<sem::U32>());
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type()); EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_EQ(sem->ConstantValue().ElementType(), sem->Type()); EXPECT_EQ(sem->ConstantValue().ElementType(), sem->Type());
@ -62,7 +66,7 @@ TEST_F(ResolverConstantsTest, Scalar_f32) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_TRUE(sem->Type()->Is<sem::F32>()); EXPECT_TRUE(sem->Type()->Is<sem::F32>());
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type()); EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_EQ(sem->ConstantValue().ElementType(), sem->Type()); EXPECT_EQ(sem->ConstantValue().ElementType(), sem->Type());
@ -77,7 +81,7 @@ TEST_F(ResolverConstantsTest, Scalar_bool) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_TRUE(sem->Type()->Is<sem::Bool>()); EXPECT_TRUE(sem->Type()->Is<sem::Bool>());
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type()); EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_EQ(sem->ConstantValue().ElementType(), sem->Type()); EXPECT_EQ(sem->ConstantValue().ElementType(), sem->Type());
@ -92,7 +96,7 @@ TEST_F(ResolverConstantsTest, Vec3_ZeroInit_i32) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::I32>()); EXPECT_TRUE(vec->type()->Is<sem::I32>());
@ -112,7 +116,7 @@ TEST_F(ResolverConstantsTest, Vec3_ZeroInit_u32) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::U32>()); EXPECT_TRUE(vec->type()->Is<sem::U32>());
@ -132,7 +136,7 @@ TEST_F(ResolverConstantsTest, Vec3_ZeroInit_f32) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::F32>()); EXPECT_TRUE(vec->type()->Is<sem::F32>());
@ -152,7 +156,7 @@ TEST_F(ResolverConstantsTest, Vec3_ZeroInit_bool) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::Bool>()); EXPECT_TRUE(vec->type()->Is<sem::Bool>());
@ -172,7 +176,7 @@ TEST_F(ResolverConstantsTest, Vec3_Splat_i32) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::I32>()); EXPECT_TRUE(vec->type()->Is<sem::I32>());
@ -192,7 +196,7 @@ TEST_F(ResolverConstantsTest, Vec3_Splat_u32) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::U32>()); EXPECT_TRUE(vec->type()->Is<sem::U32>());
@ -212,7 +216,7 @@ TEST_F(ResolverConstantsTest, Vec3_Splat_f32) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::F32>()); EXPECT_TRUE(vec->type()->Is<sem::F32>());
@ -232,7 +236,7 @@ TEST_F(ResolverConstantsTest, Vec3_Splat_bool) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::Bool>()); EXPECT_TRUE(vec->type()->Is<sem::Bool>());
@ -252,7 +256,7 @@ TEST_F(ResolverConstantsTest, Vec3_FullConstruct_i32) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::I32>()); EXPECT_TRUE(vec->type()->Is<sem::I32>());
@ -272,7 +276,7 @@ TEST_F(ResolverConstantsTest, Vec3_FullConstruct_u32) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::U32>()); EXPECT_TRUE(vec->type()->Is<sem::U32>());
@ -292,7 +296,7 @@ TEST_F(ResolverConstantsTest, Vec3_FullConstruct_f32) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::F32>()); EXPECT_TRUE(vec->type()->Is<sem::F32>());
@ -312,7 +316,7 @@ TEST_F(ResolverConstantsTest, Vec3_FullConstruct_bool) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::Bool>()); EXPECT_TRUE(vec->type()->Is<sem::Bool>());
@ -332,7 +336,7 @@ TEST_F(ResolverConstantsTest, Vec3_MixConstruct_i32) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::I32>()); EXPECT_TRUE(vec->type()->Is<sem::I32>());
@ -352,7 +356,7 @@ TEST_F(ResolverConstantsTest, Vec3_MixConstruct_u32) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::U32>()); EXPECT_TRUE(vec->type()->Is<sem::U32>());
@ -372,7 +376,7 @@ TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f32) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::F32>()); EXPECT_TRUE(vec->type()->Is<sem::F32>());
@ -392,7 +396,7 @@ TEST_F(ResolverConstantsTest, Vec3_MixConstruct_bool) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::Bool>()); EXPECT_TRUE(vec->type()->Is<sem::Bool>());
@ -412,7 +416,7 @@ TEST_F(ResolverConstantsTest, Vec3_Convert_f32_to_i32) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::I32>()); EXPECT_TRUE(vec->type()->Is<sem::I32>());
@ -432,7 +436,7 @@ TEST_F(ResolverConstantsTest, Vec3_Convert_u32_to_f32) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::F32>()); EXPECT_TRUE(vec->type()->Is<sem::F32>());
@ -452,7 +456,7 @@ TEST_F(ResolverConstantsTest, Vec3_Convert_Large_f32_to_i32) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::I32>()); EXPECT_TRUE(vec->type()->Is<sem::I32>());
@ -472,7 +476,7 @@ TEST_F(ResolverConstantsTest, Vec3_Convert_Large_f32_to_u32) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::U32>()); EXPECT_TRUE(vec->type()->Is<sem::U32>());
@ -497,7 +501,7 @@ TEST_F(ResolverConstantsTest, DISABLED_Vec3_Convert_Large_f32_to_f16) {
constexpr auto kInf = std::numeric_limits<double>::infinity(); constexpr auto kInf = std::numeric_limits<double>::infinity();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::F16>()); EXPECT_TRUE(vec->type()->Is<sem::F16>());
@ -520,7 +524,7 @@ TEST_F(ResolverConstantsTest, DISABLED_Vec3_Convert_Small_f32_to_f16) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::F16>()); EXPECT_TRUE(vec->type()->Is<sem::F16>());
@ -540,7 +544,7 @@ TEST_F(ResolverConstantsTest, Mat2x3_ZeroInit_f32) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* mat = sem->Type()->As<sem::Matrix>(); auto* mat = sem->Type()->As<sem::Matrix>();
ASSERT_NE(mat, nullptr); ASSERT_NE(mat, nullptr);
EXPECT_TRUE(mat->type()->Is<sem::F32>()); EXPECT_TRUE(mat->type()->Is<sem::F32>());
@ -564,7 +568,7 @@ TEST_F(ResolverConstantsTest, Mat3x2_Construct_Scalars_af) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* mat = sem->Type()->As<sem::Matrix>(); auto* mat = sem->Type()->As<sem::Matrix>();
ASSERT_NE(mat, nullptr); ASSERT_NE(mat, nullptr);
EXPECT_TRUE(mat->type()->Is<sem::F32>()); EXPECT_TRUE(mat->type()->Is<sem::F32>());
@ -591,7 +595,7 @@ TEST_F(ResolverConstantsTest, Mat3x2_Construct_Columns_af) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* mat = sem->Type()->As<sem::Matrix>(); auto* mat = sem->Type()->As<sem::Matrix>();
ASSERT_NE(mat, nullptr); ASSERT_NE(mat, nullptr);
EXPECT_TRUE(mat->type()->Is<sem::F32>()); EXPECT_TRUE(mat->type()->Is<sem::F32>());
@ -608,6 +612,141 @@ TEST_F(ResolverConstantsTest, Mat3x2_Construct_Columns_af) {
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(5).value, 6._a); EXPECT_EQ(sem->ConstantValue().Element<AFloat>(5).value, 6._a);
} }
TEST_F(ResolverConstantsTest, Array_i32_Zero) {
auto* expr = Construct(ty.array<i32, 4>());
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr);
ASSERT_NE(sem, nullptr);
auto* arr = sem->Type()->As<sem::Array>();
ASSERT_NE(arr, nullptr);
EXPECT_TRUE(arr->ElemType()->Is<sem::I32>());
EXPECT_EQ(arr->Count(), 4u);
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue().ElementType()->Is<sem::I32>());
ASSERT_EQ(sem->ConstantValue().ElementCount(), 4u);
EXPECT_EQ(sem->ConstantValue().Element<i32>(0).value, 0_i);
EXPECT_EQ(sem->ConstantValue().Element<i32>(1).value, 0_i);
EXPECT_EQ(sem->ConstantValue().Element<i32>(2).value, 0_i);
EXPECT_EQ(sem->ConstantValue().Element<i32>(3).value, 0_i);
}
TEST_F(ResolverConstantsTest, Array_f32_Zero) {
auto* expr = Construct(ty.array<f32, 4>());
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr);
ASSERT_NE(sem, nullptr);
auto* arr = sem->Type()->As<sem::Array>();
ASSERT_NE(arr, nullptr);
EXPECT_TRUE(arr->ElemType()->Is<sem::F32>());
EXPECT_EQ(arr->Count(), 4u);
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue().ElementType()->Is<sem::F32>());
ASSERT_EQ(sem->ConstantValue().ElementCount(), 4u);
EXPECT_EQ(sem->ConstantValue().Element<f32>(0).value, 0_f);
EXPECT_EQ(sem->ConstantValue().Element<f32>(1).value, 0_f);
EXPECT_EQ(sem->ConstantValue().Element<f32>(2).value, 0_f);
EXPECT_EQ(sem->ConstantValue().Element<f32>(3).value, 0_f);
}
TEST_F(ResolverConstantsTest, Array_vec3_f32_Zero) {
auto* expr = Construct(ty.array(ty.vec3<f32>(), 2_u));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr);
ASSERT_NE(sem, nullptr);
auto* arr = sem->Type()->As<sem::Array>();
ASSERT_NE(arr, nullptr);
EXPECT_TRUE(arr->ElemType()->Is<sem::Vector>());
EXPECT_EQ(arr->Count(), 2u);
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue().ElementType()->Is<sem::F32>());
ASSERT_EQ(sem->ConstantValue().ElementCount(), 6u);
EXPECT_EQ(sem->ConstantValue().Element<f32>(0).value, 0_f);
EXPECT_EQ(sem->ConstantValue().Element<f32>(1).value, 0_f);
EXPECT_EQ(sem->ConstantValue().Element<f32>(2).value, 0_f);
EXPECT_EQ(sem->ConstantValue().Element<f32>(3).value, 0_f);
EXPECT_EQ(sem->ConstantValue().Element<f32>(4).value, 0_f);
EXPECT_EQ(sem->ConstantValue().Element<f32>(5).value, 0_f);
}
TEST_F(ResolverConstantsTest, Array_i32_Elements) {
auto* expr = Construct(ty.array<i32, 4>(), 10_i, 20_i, 30_i, 40_i);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr);
ASSERT_NE(sem, nullptr);
auto* arr = sem->Type()->As<sem::Array>();
ASSERT_NE(arr, nullptr);
EXPECT_TRUE(arr->ElemType()->Is<sem::I32>());
EXPECT_EQ(arr->Count(), 4u);
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue().ElementType()->Is<sem::I32>());
ASSERT_EQ(sem->ConstantValue().ElementCount(), 4u);
EXPECT_EQ(sem->ConstantValue().Element<i32>(0).value, 10_i);
EXPECT_EQ(sem->ConstantValue().Element<i32>(1).value, 20_i);
EXPECT_EQ(sem->ConstantValue().Element<i32>(2).value, 30_i);
EXPECT_EQ(sem->ConstantValue().Element<i32>(3).value, 40_i);
}
TEST_F(ResolverConstantsTest, Array_f32_Elements) {
auto* expr = Construct(ty.array<f32, 4>(), 10_f, 20_f, 30_f, 40_f);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr);
ASSERT_NE(sem, nullptr);
auto* arr = sem->Type()->As<sem::Array>();
ASSERT_NE(arr, nullptr);
EXPECT_TRUE(arr->ElemType()->Is<sem::F32>());
EXPECT_EQ(arr->Count(), 4u);
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue().ElementType()->Is<sem::F32>());
ASSERT_EQ(sem->ConstantValue().ElementCount(), 4u);
EXPECT_EQ(sem->ConstantValue().Element<f32>(0).value, 10_f);
EXPECT_EQ(sem->ConstantValue().Element<f32>(1).value, 20_f);
EXPECT_EQ(sem->ConstantValue().Element<f32>(2).value, 30_f);
EXPECT_EQ(sem->ConstantValue().Element<f32>(3).value, 40_f);
}
TEST_F(ResolverConstantsTest, Array_vec3_f32_Elements) {
auto* expr = Construct(ty.array(ty.vec3<f32>(), 2_u), //
vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(4_f, 5_f, 6_f));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr);
ASSERT_NE(sem, nullptr);
auto* arr = sem->Type()->As<sem::Array>();
ASSERT_NE(arr, nullptr);
EXPECT_TRUE(arr->ElemType()->Is<sem::Vector>());
EXPECT_EQ(arr->Count(), 2u);
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue().ElementType()->Is<sem::F32>());
ASSERT_EQ(sem->ConstantValue().ElementCount(), 6u);
EXPECT_EQ(sem->ConstantValue().Element<f32>(0).value, 1_f);
EXPECT_EQ(sem->ConstantValue().Element<f32>(1).value, 2_f);
EXPECT_EQ(sem->ConstantValue().Element<f32>(2).value, 3_f);
EXPECT_EQ(sem->ConstantValue().Element<f32>(3).value, 4_f);
EXPECT_EQ(sem->ConstantValue().Element<f32>(4).value, 5_f);
EXPECT_EQ(sem->ConstantValue().Element<f32>(5).value, 6_f);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Indexing
////////////////////////////////////////////////////////////////////////////////////////////////////
TEST_F(ResolverConstantsTest, Vec3_Index) { TEST_F(ResolverConstantsTest, Vec3_Index) {
auto* expr = IndexAccessor(vec3<i32>(1_i, 2_i, 3_i), 2_i); auto* expr = IndexAccessor(vec3<i32>(1_i, 2_i, 3_i), 2_i);
WrapInFunction(expr); WrapInFunction(expr);
@ -615,7 +754,7 @@ TEST_F(ResolverConstantsTest, Vec3_Index) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
ASSERT_TRUE(sem->Type()->Is<sem::I32>()); ASSERT_TRUE(sem->Type()->Is<sem::I32>());
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type()); EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue().ElementType()->Is<sem::I32>()); EXPECT_TRUE(sem->ConstantValue().ElementType()->Is<sem::I32>());
@ -631,7 +770,7 @@ TEST_F(ResolverConstantsTest, Vec3_Index_OOB_High) {
EXPECT_EQ(r()->error(), "12:34 warning: index 3 out of bounds [0..2]. Clamping index to 2"); EXPECT_EQ(r()->error(), "12:34 warning: index 3 out of bounds [0..2]. Clamping index to 2");
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
ASSERT_TRUE(sem->Type()->Is<sem::I32>()); ASSERT_TRUE(sem->Type()->Is<sem::I32>());
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type()); EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue().ElementType()->Is<sem::I32>()); EXPECT_TRUE(sem->ConstantValue().ElementType()->Is<sem::I32>());
@ -647,7 +786,7 @@ TEST_F(ResolverConstantsTest, Vec3_Index_OOB_Low) {
EXPECT_EQ(r()->error(), "12:34 warning: index -3 out of bounds [0..2]. Clamping index to 0"); EXPECT_EQ(r()->error(), "12:34 warning: index -3 out of bounds [0..2]. Clamping index to 0");
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
ASSERT_TRUE(sem->Type()->Is<sem::I32>()); ASSERT_TRUE(sem->Type()->Is<sem::I32>());
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type()); EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue().ElementType()->Is<sem::I32>()); EXPECT_TRUE(sem->ConstantValue().ElementType()->Is<sem::I32>());
@ -663,7 +802,7 @@ TEST_F(ResolverConstantsTest, Mat3x2_Index) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_EQ(vec->Width(), 2u); EXPECT_EQ(vec->Width(), 2u);
@ -684,7 +823,7 @@ TEST_F(ResolverConstantsTest, Mat3x2_Index_OOB_High) {
EXPECT_EQ(r()->error(), "12:34 warning: index 3 out of bounds [0..2]. Clamping index to 2"); EXPECT_EQ(r()->error(), "12:34 warning: index 3 out of bounds [0..2]. Clamping index to 2");
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_EQ(vec->Width(), 2u); EXPECT_EQ(vec->Width(), 2u);
@ -705,7 +844,7 @@ TEST_F(ResolverConstantsTest, Mat3x2_Index_OOB_Low) {
EXPECT_EQ(r()->error(), "12:34 warning: index -3 out of bounds [0..2]. Clamping index to 0"); EXPECT_EQ(r()->error(), "12:34 warning: index -3 out of bounds [0..2]. Clamping index to 0");
auto* sem = Sem().Get(expr); auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>(); auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr); ASSERT_NE(vec, nullptr);
EXPECT_EQ(vec->Width(), 2u); EXPECT_EQ(vec->Width(), 2u);
@ -716,5 +855,190 @@ TEST_F(ResolverConstantsTest, Mat3x2_Index_OOB_Low) {
EXPECT_EQ(sem->ConstantValue().Element<f32>(1).value, 2._a); EXPECT_EQ(sem->ConstantValue().Element<f32>(1).value, 2._a);
} }
TEST_F(ResolverConstantsTest, Array_vec3_f32_Index) {
auto* expr = IndexAccessor(Construct(ty.array(ty.vec3<f32>(), 2_u), //
vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(4_f, 5_f, 6_f)),
1_i);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr);
ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::F32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue().ElementType()->Is<sem::F32>());
ASSERT_EQ(sem->ConstantValue().ElementCount(), 3u);
EXPECT_EQ(sem->ConstantValue().Element<f32>(0).value, 4_f);
EXPECT_EQ(sem->ConstantValue().Element<f32>(1).value, 5_f);
EXPECT_EQ(sem->ConstantValue().Element<f32>(2).value, 6_f);
}
TEST_F(ResolverConstantsTest, Array_vec3_f32_Index_OOB_High) {
auto* expr = IndexAccessor(Construct(ty.array(ty.vec3<f32>(), 2_u), //
vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(4_f, 5_f, 6_f)),
Expr(Source{{12, 34}}, 2_i));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_EQ(r()->error(), "12:34 warning: index 2 out of bounds [0..1]. Clamping index to 1");
auto* sem = Sem().Get(expr);
ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::F32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue().ElementType()->Is<sem::F32>());
ASSERT_EQ(sem->ConstantValue().ElementCount(), 3u);
EXPECT_EQ(sem->ConstantValue().Element<f32>(0).value, 4_f);
EXPECT_EQ(sem->ConstantValue().Element<f32>(1).value, 5_f);
EXPECT_EQ(sem->ConstantValue().Element<f32>(2).value, 6_f);
}
TEST_F(ResolverConstantsTest, Array_vec3_f32_Index_OOB_Low) {
auto* expr = IndexAccessor(Construct(ty.array(ty.vec3<f32>(), 2_u), //
vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(4_f, 5_f, 6_f)),
Expr(Source{{12, 34}}, -2_i));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_EQ(r()->error(), "12:34 warning: index -2 out of bounds [0..1]. Clamping index to 0");
auto* sem = Sem().Get(expr);
ASSERT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::F32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue().ElementType()->Is<sem::F32>());
ASSERT_EQ(sem->ConstantValue().ElementCount(), 3u);
EXPECT_EQ(sem->ConstantValue().Element<f32>(0).value, 1_f);
EXPECT_EQ(sem->ConstantValue().Element<f32>(1).value, 2_f);
EXPECT_EQ(sem->ConstantValue().Element<f32>(2).value, 3_f);
}
TEST_F(ResolverConstantsTest, ChainedIndex) {
auto* arr_expr = Construct(ty.array(ty.mat2x3<f32>(), 2_u), // array<mat2x3<f32>, 2u>
mat2x3<f32>(vec3<f32>(1_f, 2_f, 3_f), //
vec3<f32>(4_f, 5_f, 6_f)), //
mat2x3<f32>(vec3<f32>(7_f, 8_f, 9_f), //
vec3<f32>(10_f, 11_f, 12_f)));
auto* mat_expr = IndexAccessor(arr_expr, 1_i); // arr[1]
auto* vec_expr = IndexAccessor(mat_expr, 0_i); // arr[1][0]
auto* f32_expr = IndexAccessor(vec_expr, 2_i); // arr[1][0][2]
WrapInFunction(f32_expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
{
auto* mat = Sem().Get(mat_expr);
EXPECT_NE(mat, nullptr);
auto* ty = mat->Type()->As<sem::Matrix>();
ASSERT_NE(mat->Type(), nullptr);
EXPECT_TRUE(ty->ColumnType()->Is<sem::Vector>());
EXPECT_EQ(ty->columns(), 2u);
EXPECT_EQ(ty->rows(), 3u);
EXPECT_EQ(mat->ConstantValue().Type(), mat->Type());
EXPECT_TRUE(mat->ConstantValue().ElementType()->Is<sem::F32>());
ASSERT_EQ(mat->ConstantValue().ElementCount(), 6u);
EXPECT_EQ(mat->ConstantValue().Element<f32>(0).value, 7_f);
EXPECT_EQ(mat->ConstantValue().Element<f32>(1).value, 8_f);
EXPECT_EQ(mat->ConstantValue().Element<f32>(2).value, 9_f);
EXPECT_EQ(mat->ConstantValue().Element<f32>(3).value, 10_f);
EXPECT_EQ(mat->ConstantValue().Element<f32>(4).value, 11_f);
EXPECT_EQ(mat->ConstantValue().Element<f32>(5).value, 12_f);
}
{
auto* vec = Sem().Get(vec_expr);
EXPECT_NE(vec, nullptr);
auto* ty = vec->Type()->As<sem::Vector>();
ASSERT_NE(vec->Type(), nullptr);
EXPECT_TRUE(ty->type()->Is<sem::F32>());
EXPECT_EQ(ty->Width(), 3u);
EXPECT_EQ(vec->ConstantValue().Type(), vec->Type());
EXPECT_TRUE(vec->ConstantValue().ElementType()->Is<sem::F32>());
ASSERT_EQ(vec->ConstantValue().ElementCount(), 3u);
EXPECT_EQ(vec->ConstantValue().Element<f32>(0).value, 7_f);
EXPECT_EQ(vec->ConstantValue().Element<f32>(1).value, 8_f);
EXPECT_EQ(vec->ConstantValue().Element<f32>(2).value, 9_f);
}
{
auto* f = Sem().Get(f32_expr);
EXPECT_NE(f, nullptr);
EXPECT_TRUE(f->Type()->Is<sem::F32>());
EXPECT_EQ(f->ConstantValue().Type(), f->Type());
EXPECT_TRUE(f->ConstantValue().ElementType()->Is<sem::F32>());
ASSERT_EQ(f->ConstantValue().ElementCount(), 1u);
EXPECT_EQ(f->ConstantValue().Element<f32>(0).value, 9_f);
}
}
TEST_F(ResolverConstantsTest, ChainedIndex_OOB) {
auto* arr_expr = Construct(ty.array(ty.mat2x3<f32>(), 2_u), // array<mat2x3<f32>, 2u>
mat2x3<f32>(vec3<f32>(1_f, 2_f, 3_f), //
vec3<f32>(4_f, 5_f, 6_f)), //
mat2x3<f32>(vec3<f32>(7_f, 8_f, 9_f), //
vec3<f32>(10_f, 11_f, 12_f)));
auto* mat_expr = IndexAccessor(arr_expr, Expr(Source{{1, 2}}, -3_i)); // arr[3]
auto* vec_expr = IndexAccessor(mat_expr, Expr(Source{{3, 4}}, -2_i)); // arr[3][-2]
auto* f32_expr = IndexAccessor(vec_expr, Expr(Source{{5, 6}}, 4_i)); // arr[3][-2][4]
WrapInFunction(f32_expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_EQ(r()->error(), R"(1:2 warning: index -3 out of bounds [0..1]. Clamping index to 0
3:4 warning: index -2 out of bounds [0..1]. Clamping index to 0
5:6 warning: index 4 out of bounds [0..2]. Clamping index to 2)");
{
auto* mat = Sem().Get(mat_expr);
EXPECT_NE(mat, nullptr);
auto* ty = mat->Type()->As<sem::Matrix>();
ASSERT_NE(mat->Type(), nullptr);
EXPECT_TRUE(ty->ColumnType()->Is<sem::Vector>());
EXPECT_EQ(ty->columns(), 2u);
EXPECT_EQ(ty->rows(), 3u);
EXPECT_EQ(mat->ConstantValue().Type(), mat->Type());
EXPECT_TRUE(mat->ConstantValue().ElementType()->Is<sem::F32>());
ASSERT_EQ(mat->ConstantValue().ElementCount(), 6u);
EXPECT_EQ(mat->ConstantValue().Element<f32>(0).value, 1_f);
EXPECT_EQ(mat->ConstantValue().Element<f32>(1).value, 2_f);
EXPECT_EQ(mat->ConstantValue().Element<f32>(2).value, 3_f);
EXPECT_EQ(mat->ConstantValue().Element<f32>(3).value, 4_f);
EXPECT_EQ(mat->ConstantValue().Element<f32>(4).value, 5_f);
EXPECT_EQ(mat->ConstantValue().Element<f32>(5).value, 6_f);
}
{
auto* vec = Sem().Get(vec_expr);
EXPECT_NE(vec, nullptr);
auto* ty = vec->Type()->As<sem::Vector>();
ASSERT_NE(vec->Type(), nullptr);
EXPECT_TRUE(ty->type()->Is<sem::F32>());
EXPECT_EQ(ty->Width(), 3u);
EXPECT_EQ(vec->ConstantValue().Type(), vec->Type());
EXPECT_TRUE(vec->ConstantValue().ElementType()->Is<sem::F32>());
ASSERT_EQ(vec->ConstantValue().ElementCount(), 3u);
EXPECT_EQ(vec->ConstantValue().Element<f32>(0).value, 1_f);
EXPECT_EQ(vec->ConstantValue().Element<f32>(1).value, 2_f);
EXPECT_EQ(vec->ConstantValue().Element<f32>(2).value, 3_f);
}
{
auto* f = Sem().Get(f32_expr);
EXPECT_NE(f, nullptr);
EXPECT_TRUE(f->Type()->Is<sem::F32>());
EXPECT_EQ(f->ConstantValue().Type(), f->Type());
EXPECT_TRUE(f->ConstantValue().ElementType()->Is<sem::F32>());
ASSERT_EQ(f->ConstantValue().ElementCount(), 1u);
EXPECT_EQ(f->ConstantValue().Element<f32>(0).value, 3_f);
}
}
} // namespace } // namespace
} // namespace tint::resolver } // namespace tint::resolver

View File

@ -97,18 +97,19 @@ bool Constant::AllEqual(size_t start, size_t end) const {
const Type* Constant::CheckElemType(const sem::Type* ty, size_t num_elements) { const Type* Constant::CheckElemType(const sem::Type* ty, size_t num_elements) {
diag::List diag; diag::List diag;
if (ty->is_abstract_or_scalar() || ty->IsAnyOf<Vector, Matrix>()) {
uint32_t count = 0; uint32_t count = 0;
auto* el_ty = Type::DeepestElementOf(ty, &count); auto* el_ty = Type::DeepestElementOf(ty, &count);
if (!el_ty) {
TINT_ICE(Semantic, diag) << "Unsupported sem::Constant type: " << ty->TypeInfo().name;
return nullptr;
}
if (num_elements != count) { if (num_elements != count) {
TINT_ICE(Semantic, diag) << "sem::Constant() type <-> element mismatch. type: '" TINT_ICE(Semantic, diag) << "sem::Constant() type <-> element mismatch. type: '"
<< ty->TypeInfo().name << "' element: " << num_elements; << ty->TypeInfo().name << "' provided: " << num_elements
<< " require: " << count;
} }
TINT_ASSERT(Semantic, el_ty->is_abstract_or_scalar()); TINT_ASSERT(Semantic, el_ty->is_abstract_or_scalar());
return el_ty; return el_ty;
}
TINT_UNREACHABLE(Semantic, diag) << "Unsupported sem::Constant type: " << ty->TypeInfo().name;
return nullptr;
} }
} // namespace tint::sem } // namespace tint::sem

View File

@ -25,7 +25,16 @@ using namespace tint::number_suffixes; // NOLINT
namespace tint::sem { namespace tint::sem {
namespace { namespace {
using ConstantTest = TestHelper; struct ConstantTest : public TestHelper {
const sem::Array* Array(uint32_t n, const sem::Type* el_ty) {
return create<sem::Array>(el_ty,
/* count */ n,
/* align */ 16u,
/* size */ 4u * n,
/* stride */ 16u * n,
/* implicit_stride */ 16u * n);
}
};
TEST_F(ConstantTest, ConstructorInitializerList) { TEST_F(ConstantTest, ConstructorInitializerList) {
{ {
@ -259,6 +268,133 @@ TEST_F(ConstantTest, Element_mat2x3_f16) {
EXPECT_TYPE(c.ElementType(), el_ty); EXPECT_TYPE(c.ElementType(), el_ty);
} }
TEST_F(ConstantTest, Element_arr_vec3_ai) {
auto* el_ty = create<AbstractInt>();
auto* ty = Array(2, create<Vector>(el_ty, 3u));
Constant c(ty, {1_a, 2_a, 3_a, 4_a, 5_a, 6_a});
EXPECT_EQ(c.Element<AInt>(0), 1_a);
EXPECT_EQ(c.Element<AInt>(1), 2_a);
EXPECT_EQ(c.Element<AInt>(2), 3_a);
EXPECT_EQ(c.Element<AInt>(3), 4_a);
EXPECT_EQ(c.Element<AInt>(4), 5_a);
EXPECT_EQ(c.Element<AInt>(5), 6_a);
EXPECT_EQ(c.ElementCount(), 6u);
EXPECT_TYPE(c.Type(), ty);
EXPECT_TYPE(c.ElementType(), el_ty);
}
TEST_F(ConstantTest, Element_arr_vec3_i32) {
auto* el_ty = create<I32>();
auto* ty = Array(2, create<Vector>(el_ty, 3u));
Constant c(ty, {1_a, 2_a, 3_a, 4_a, 5_a, 6_a});
EXPECT_EQ(c.Element<i32>(0), 1_i);
EXPECT_EQ(c.Element<i32>(1), 2_i);
EXPECT_EQ(c.Element<i32>(2), 3_i);
EXPECT_EQ(c.Element<i32>(3), 4_i);
EXPECT_EQ(c.Element<i32>(4), 5_i);
EXPECT_EQ(c.Element<i32>(5), 6_i);
EXPECT_EQ(c.ElementCount(), 6u);
EXPECT_TYPE(c.Type(), ty);
EXPECT_TYPE(c.ElementType(), el_ty);
}
TEST_F(ConstantTest, Element_arr_vec3_u32) {
auto* el_ty = create<U32>();
auto* ty = Array(2, create<Vector>(el_ty, 3u));
Constant c(ty, {1_a, 2_a, 3_a, 4_a, 5_a, 6_a});
EXPECT_EQ(c.Element<u32>(0), 1_u);
EXPECT_EQ(c.Element<u32>(1), 2_u);
EXPECT_EQ(c.Element<u32>(2), 3_u);
EXPECT_EQ(c.Element<u32>(3), 4_u);
EXPECT_EQ(c.Element<u32>(4), 5_u);
EXPECT_EQ(c.Element<u32>(5), 6_u);
EXPECT_EQ(c.ElementCount(), 6u);
EXPECT_TYPE(c.Type(), ty);
EXPECT_TYPE(c.ElementType(), el_ty);
}
TEST_F(ConstantTest, Element_arr_vec3_bool) {
auto* el_ty = create<Bool>();
auto* ty = Array(2, create<Vector>(el_ty, 2u));
Constant c(ty, {true, false, false, true});
EXPECT_EQ(c.Element<bool>(0), true);
EXPECT_EQ(c.Element<bool>(1), false);
EXPECT_EQ(c.Element<bool>(2), false);
EXPECT_EQ(c.Element<bool>(3), true);
EXPECT_EQ(c.ElementCount(), 4u);
EXPECT_TYPE(c.Type(), ty);
EXPECT_TYPE(c.ElementType(), el_ty);
}
TEST_F(ConstantTest, Element_arr_vec3_af) {
auto* el_ty = create<AbstractFloat>();
auto* ty = Array(2, create<Vector>(el_ty, 3u));
Constant c(ty, {1.0_a, 2.0_a, 3.0_a, 4.0_a, 5.0_a, 6.0_a});
EXPECT_EQ(c.Element<AFloat>(0), 1.0_a);
EXPECT_EQ(c.Element<AFloat>(1), 2.0_a);
EXPECT_EQ(c.Element<AFloat>(2), 3.0_a);
EXPECT_EQ(c.Element<AFloat>(3), 4.0_a);
EXPECT_EQ(c.Element<AFloat>(4), 5.0_a);
EXPECT_EQ(c.Element<AFloat>(5), 6.0_a);
EXPECT_EQ(c.ElementCount(), 6u);
EXPECT_TYPE(c.Type(), ty);
EXPECT_TYPE(c.ElementType(), el_ty);
}
TEST_F(ConstantTest, Element_arr_vec3_f32) {
auto* el_ty = create<F32>();
auto* ty = Array(2, create<Vector>(el_ty, 3u));
Constant c(ty, {1.0_a, 2.0_a, 3.0_a, 4.0_a, 5.0_a, 6.0_a});
EXPECT_EQ(c.Element<f32>(0), 1.0_f);
EXPECT_EQ(c.Element<f32>(1), 2.0_f);
EXPECT_EQ(c.Element<f32>(2), 3.0_f);
EXPECT_EQ(c.Element<f32>(3), 4.0_f);
EXPECT_EQ(c.Element<f32>(4), 5.0_f);
EXPECT_EQ(c.Element<f32>(5), 6.0_f);
EXPECT_EQ(c.ElementCount(), 6u);
EXPECT_TYPE(c.Type(), ty);
EXPECT_TYPE(c.ElementType(), el_ty);
}
TEST_F(ConstantTest, Element_arr_vec3_f16) {
auto* el_ty = create<F16>();
auto* ty = Array(2, create<Vector>(el_ty, 3u));
Constant c(ty, {1.0_a, 2.0_a, 3.0_a, 4.0_a, 5.0_a, 6.0_a});
EXPECT_EQ(c.Element<f16>(0), 1.0_h);
EXPECT_EQ(c.Element<f16>(1), 2.0_h);
EXPECT_EQ(c.Element<f16>(2), 3.0_h);
EXPECT_EQ(c.Element<f16>(3), 4.0_h);
EXPECT_EQ(c.Element<f16>(4), 5.0_h);
EXPECT_EQ(c.Element<f16>(5), 6.0_h);
EXPECT_EQ(c.ElementCount(), 6u);
EXPECT_TYPE(c.Type(), ty);
EXPECT_TYPE(c.ElementType(), el_ty);
}
TEST_F(ConstantTest, Element_arr_arr_mat2x3_f32) {
auto* el_ty = create<F32>();
auto* ty = Array(2, Array(2, create<Matrix>(create<Vector>(el_ty, 3u), 2u)));
Constant c(ty, {
1.0_a, 2.0_a, 3.0_a, //
4.0_a, 5.0_a, 6.0_a, //
7.0_a, 8.0_a, 9.0_a, //
10.0_a, 11.0_a, 12.0_a, //
13.0_a, 14.0_a, 15.0_a, //
16.0_a, 17.0_a, 18.0_a, //
19.0_a, 20.0_a, 21.0_a, //
22.0_a, 23.0_a, 24.0_a, //
});
for (size_t i = 0; i < 24; i++) {
EXPECT_EQ(c.Element<f32>(i), f32(i + 1));
}
EXPECT_EQ(c.ElementCount(), 24u);
EXPECT_TYPE(c.Type(), ty);
EXPECT_TYPE(c.ElementType(), el_ty);
}
TEST_F(ConstantTest, AnyZero) { TEST_F(ConstantTest, AnyZero) {
auto* vec3_ai = create<Vector>(create<AbstractInt>(), 3u); auto* vec3_ai = create<Vector>(create<AbstractInt>(), 3u);
EXPECT_EQ(Constant(vec3_ai, {1_a, 2_a, 3_a}).AnyZero(), false); EXPECT_EQ(Constant(vec3_ai, {1_a, 2_a, 3_a}).AnyZero(), false);

View File

@ -1767,9 +1767,14 @@ bool GeneratorImpl::EmitDiscard(const ast::DiscardStatement*) {
bool GeneratorImpl::EmitExpression(std::ostream& out, const ast::Expression* expr) { bool GeneratorImpl::EmitExpression(std::ostream& out, const ast::Expression* expr) {
if (auto* sem = builder_.Sem().Get(expr)) { if (auto* sem = builder_.Sem().Get(expr)) {
if (auto constant = sem->ConstantValue()) { if (auto constant = sem->ConstantValue()) {
// We do not want to inline array constants, as this will undo the work of
// PromoteInitializersToConstVar, which ensures that arrays are declarated in 'let's
// before their usage.
if (!constant.Type()->Is<sem::Array>()) {
return EmitConstant(out, constant); return EmitConstant(out, constant);
} }
} }
}
return Switch( return Switch(
expr, expr,
[&](const ast::IndexAccessorExpression* a) { // [&](const ast::IndexAccessorExpression* a) { //
@ -2258,8 +2263,7 @@ bool GeneratorImpl::EmitConstantRange(std::ostream& out,
return true; return true;
}, },
[&](const sem::Matrix* m) { [&](const sem::Matrix* m) {
if (!EmitType(out, constant.Type(), ast::StorageClass::kNone, ast::Access::kUndefined, if (!EmitType(out, m, ast::StorageClass::kNone, ast::Access::kUndefined, "")) {
"")) {
return false; return false;
} }

View File

@ -156,12 +156,11 @@ void main() {
TEST_F(GlslSanitizerTest, PromoteArrayInitializerToConstVar) { TEST_F(GlslSanitizerTest, PromoteArrayInitializerToConstVar) {
auto* array_init = array<i32, 4>(1_i, 2_i, 3_i, 4_i); auto* array_init = array<i32, 4>(1_i, 2_i, 3_i, 4_i);
auto* array_index = IndexAccessor(array_init, 3_i);
auto* pos = Var("pos", ty.i32(), ast::StorageClass::kNone, array_index);
Func("main", {}, ty.void_(), Func("main", {}, ty.void_(),
{ {
Decl(pos), Decl(Var("idx", nullptr, Expr(3_i))),
Decl(Var("pos", ty.i32(), IndexAccessor(array_init, "idx"))),
}, },
{ {
Stage(ast::PipelineStage::kFragment), Stage(ast::PipelineStage::kFragment),
@ -176,8 +175,9 @@ TEST_F(GlslSanitizerTest, PromoteArrayInitializerToConstVar) {
precision mediump float; precision mediump float;
void tint_symbol() { void tint_symbol() {
int idx = 3;
int tint_symbol_1[4] = int[4](1, 2, 3, 4); int tint_symbol_1[4] = int[4](1, 2, 3, 4);
int pos = tint_symbol_1[3]; int pos = tint_symbol_1[idx];
} }
void main() { void main() {

View File

@ -2651,9 +2651,14 @@ bool GeneratorImpl::EmitDiscard(const ast::DiscardStatement*) {
bool GeneratorImpl::EmitExpression(std::ostream& out, const ast::Expression* expr) { bool GeneratorImpl::EmitExpression(std::ostream& out, const ast::Expression* expr) {
if (auto* sem = builder_.Sem().Get(expr)) { if (auto* sem = builder_.Sem().Get(expr)) {
if (auto constant = sem->ConstantValue()) { if (auto constant = sem->ConstantValue()) {
// We do not want to inline array constants, as this will undo the work of
// PromoteInitializersToConstVar, which ensures that arrays are declarated in 'let's
// before their usage.
if (!constant.Type()->Is<sem::Array>()) {
return EmitConstant(out, constant); return EmitConstant(out, constant);
} }
} }
}
return Switch( return Switch(
expr, expr,
[&](const ast::IndexAccessorExpression* a) { // [&](const ast::IndexAccessorExpression* a) { //

View File

@ -188,12 +188,11 @@ void a_func() {
TEST_F(HlslSanitizerTest, PromoteArrayInitializerToConstVar) { TEST_F(HlslSanitizerTest, PromoteArrayInitializerToConstVar) {
auto* array_init = array<i32, 4>(1_i, 2_i, 3_i, 4_i); auto* array_init = array<i32, 4>(1_i, 2_i, 3_i, 4_i);
auto* array_index = IndexAccessor(array_init, 3_i);
auto* pos = Var("pos", ty.i32(), ast::StorageClass::kNone, array_index);
Func("main", {}, ty.void_(), Func("main", {}, ty.void_(),
{ {
Decl(pos), Decl(Var("idx", nullptr, Expr(3_i))),
Decl(Var("pos", ty.i32(), IndexAccessor(array_init, "idx"))),
}, },
{ {
Stage(ast::PipelineStage::kFragment), Stage(ast::PipelineStage::kFragment),
@ -205,8 +204,9 @@ TEST_F(HlslSanitizerTest, PromoteArrayInitializerToConstVar) {
auto got = gen.result(); auto got = gen.result();
auto* expect = R"(void main() { auto* expect = R"(void main() {
int idx = 3;
const int tint_symbol[4] = {1, 2, 3, 4}; const int tint_symbol[4] = {1, 2, 3, 4};
int pos = tint_symbol[3]; int pos = tint_symbol[idx];
return; return;
} }
)"; )";

View File

@ -1691,9 +1691,14 @@ bool GeneratorImpl::EmitLiteral(std::ostream& out, const ast::LiteralExpression*
bool GeneratorImpl::EmitExpression(std::ostream& out, const ast::Expression* expr) { bool GeneratorImpl::EmitExpression(std::ostream& out, const ast::Expression* expr) {
if (auto* sem = builder_.Sem().Get(expr)) { if (auto* sem = builder_.Sem().Get(expr)) {
if (auto constant = sem->ConstantValue()) { if (auto constant = sem->ConstantValue()) {
// We do not want to inline array constants, as this will undo the work of
// PromoteInitializersToConstVar, which ensures that arrays are declarated in 'let's
// before their usage.
if (!constant.Type()->Is<sem::Array>()) {
return EmitConstant(out, constant); return EmitConstant(out, constant);
} }
} }
}
return Switch( return Switch(
expr, expr,
[&](const ast::IndexAccessorExpression* a) { // [&](const ast::IndexAccessorExpression* a) { //

View File

@ -274,18 +274,13 @@ TEST_F(BuilderTest, Const_IndexAccessor_Array_MultiLevel) {
%16 = OpConstant %7 6 %16 = OpConstant %7 6
%17 = OpConstantComposite %6 %14 %15 %16 %17 = OpConstantComposite %6 %14 %15 %16
%18 = OpConstantComposite %5 %13 %17 %18 = OpConstantComposite %5 %13 %17
%19 = OpTypeInt 32 1 %20 = OpTypePointer Function %7
%20 = OpConstant %19 1 %21 = OpConstantNull %7
%22 = OpConstant %19 2
%25 = OpTypePointer Function %7
%26 = OpConstantNull %7
)"); )");
EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%24 = OpVariable %25 Function %26 EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%19 = OpVariable %20 Function %21
)"); )");
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
R"(%21 = OpCompositeExtract %6 %18 1 R"(OpStore %19 %16
%23 = OpCompositeExtract %7 %21 2
OpStore %24 %23
OpReturn OpReturn
)"); )");
@ -546,16 +541,12 @@ TEST_F(BuilderTest, Const_IndexAccessor_Nested_Array_f32) {
%14 = OpConstantComposite %6 %13 %13 %14 = OpConstantComposite %6 %13 %13
%15 = OpConstantComposite %6 %11 %13 %15 = OpConstantComposite %6 %11 %13
%16 = OpConstantComposite %5 %12 %14 %15 %16 = OpConstantComposite %5 %12 %14 %15
%17 = OpConstant %8 1 %18 = OpTypePointer Function %7
%19 = OpConstantNull %8
%22 = OpTypePointer Function %7
)"); )");
EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%21 = OpVariable %22 Function %10 EXPECT_EQ(DumpInstructions(b.functions()[0].variables()), R"(%17 = OpVariable %18 Function %10
)"); )");
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
R"(%18 = OpCompositeExtract %6 %16 1 R"(OpStore %17 %13
%20 = OpCompositeExtract %7 %18 0
OpStore %21 %20
OpReturn OpReturn
)"); )");

View File

@ -4,7 +4,7 @@ void tint_symbol() {
int x = 42; int x = 42;
int empty[4] = int[4](0, 0, 0, 0); int empty[4] = int[4](0, 0, 0, 0);
int nonempty[4] = int[4](1, 2, 3, 4); int nonempty[4] = int[4](1, 2, 3, 4);
int nonempty_with_expr[4] = int[4](1, 42, (42 + 1), nonempty[3]); int nonempty_with_expr[4] = int[4](1, 42, (42 + 1), 4);
int nested_empty[2][3][4] = int[2][3][4](int[3][4](int[4](0, 0, 0, 0), int[4](0, 0, 0, 0), int[4](0, 0, 0, 0)), int[3][4](int[4](0, 0, 0, 0), int[4](0, 0, 0, 0), int[4](0, 0, 0, 0))); int nested_empty[2][3][4] = int[2][3][4](int[3][4](int[4](0, 0, 0, 0), int[4](0, 0, 0, 0), int[4](0, 0, 0, 0)), int[3][4](int[4](0, 0, 0, 0), int[4](0, 0, 0, 0), int[4](0, 0, 0, 0)));
int tint_symbol_1[4] = int[4](1, 2, 3, 4); int tint_symbol_1[4] = int[4](1, 2, 3, 4);
int tint_symbol_2[4] = int[4](5, 6, 7, 8); int tint_symbol_2[4] = int[4](5, 6, 7, 8);
@ -16,14 +16,14 @@ void tint_symbol() {
int tint_symbol_8[3][4] = int[3][4](tint_symbol_5, tint_symbol_6, tint_symbol_7); int tint_symbol_8[3][4] = int[3][4](tint_symbol_5, tint_symbol_6, tint_symbol_7);
int nested_nonempty[2][3][4] = int[2][3][4](tint_symbol_4, tint_symbol_8); int nested_nonempty[2][3][4] = int[2][3][4](tint_symbol_4, tint_symbol_8);
int tint_symbol_9[4] = int[4](1, 2, 42, (42 + 1)); int tint_symbol_9[4] = int[4](1, 2, 42, (42 + 1));
int tint_symbol_10[4] = int[4](5, 6, nonempty[2], (nonempty[3] + 1)); int tint_symbol_10[4] = int[4](5, 6, 3, (4 + 1));
int tint_symbol_11[3][4] = int[3][4](tint_symbol_9, tint_symbol_10, nonempty); int tint_symbol_11[3][4] = int[3][4](tint_symbol_9, tint_symbol_10, nonempty);
int nested_nonempty_with_expr[2][3][4] = int[2][3][4](tint_symbol_11, nested_nonempty[1]); int nested_nonempty_with_expr[2][3][4] = int[2][3][4](tint_symbol_11, nested_nonempty[1]);
int tint_symbol_12[4] = int[4](0, 0, 0, 0); int tint_symbol_12[4] = int[4](0, 0, 0, 0);
int subexpr_empty = tint_symbol_12[1]; int subexpr_empty = 0;
int tint_symbol_13[4] = int[4](1, 2, 3, 4); int tint_symbol_13[4] = int[4](1, 2, 3, 4);
int subexpr_nonempty = tint_symbol_13[2]; int subexpr_nonempty = 3;
int tint_symbol_14[4] = int[4](1, 42, (42 + 1), nonempty[3]); int tint_symbol_14[4] = int[4](1, 42, (42 + 1), 4);
int subexpr_nonempty_with_expr = tint_symbol_14[2]; int subexpr_nonempty_with_expr = tint_symbol_14[2];
int tint_symbol_15[2][4] = int[2][4](int[4](0, 0, 0, 0), int[4](0, 0, 0, 0)); int tint_symbol_15[2][4] = int[2][4](int[4](0, 0, 0, 0), int[4](0, 0, 0, 0));
int subexpr_nested_empty[4] = tint_symbol_15[1]; int subexpr_nested_empty[4] = tint_symbol_15[1];
@ -31,7 +31,7 @@ void tint_symbol() {
int tint_symbol_17[4] = int[4](5, 6, 7, 8); int tint_symbol_17[4] = int[4](5, 6, 7, 8);
int tint_symbol_18[2][4] = int[2][4](tint_symbol_16, tint_symbol_17); int tint_symbol_18[2][4] = int[2][4](tint_symbol_16, tint_symbol_17);
int subexpr_nested_nonempty[4] = tint_symbol_18[1]; int subexpr_nested_nonempty[4] = tint_symbol_18[1];
int tint_symbol_19[4] = int[4](1, 42, (42 + 1), nonempty[3]); int tint_symbol_19[4] = int[4](1, 42, (42 + 1), 4);
int tint_symbol_20[2][4] = int[2][4](tint_symbol_19, nested_nonempty[1][2]); int tint_symbol_20[2][4] = int[2][4](tint_symbol_19, nested_nonempty[1][2]);
int subexpr_nested_nonempty_with_expr[4] = tint_symbol_20[1]; int subexpr_nested_nonempty_with_expr[4] = tint_symbol_20[1];
} }

View File

@ -3,7 +3,7 @@ void main() {
const int x = 42; const int x = 42;
const int empty[4] = (int[4])0; const int empty[4] = (int[4])0;
const int nonempty[4] = {1, 2, 3, 4}; const int nonempty[4] = {1, 2, 3, 4};
const int nonempty_with_expr[4] = {1, 42, (42 + 1), nonempty[3]}; const int nonempty_with_expr[4] = {1, 42, (42 + 1), 4};
const int nested_empty[2][3][4] = (int[2][3][4])0; const int nested_empty[2][3][4] = (int[2][3][4])0;
const int tint_symbol[4] = {1, 2, 3, 4}; const int tint_symbol[4] = {1, 2, 3, 4};
const int tint_symbol_1[4] = {5, 6, 7, 8}; const int tint_symbol_1[4] = {5, 6, 7, 8};
@ -15,14 +15,14 @@ void main() {
const int tint_symbol_7[3][4] = {tint_symbol_4, tint_symbol_5, tint_symbol_6}; const int tint_symbol_7[3][4] = {tint_symbol_4, tint_symbol_5, tint_symbol_6};
const int nested_nonempty[2][3][4] = {tint_symbol_3, tint_symbol_7}; const int nested_nonempty[2][3][4] = {tint_symbol_3, tint_symbol_7};
const int tint_symbol_8[4] = {1, 2, 42, (42 + 1)}; const int tint_symbol_8[4] = {1, 2, 42, (42 + 1)};
const int tint_symbol_9[4] = {5, 6, nonempty[2], (nonempty[3] + 1)}; const int tint_symbol_9[4] = {5, 6, 3, (4 + 1)};
const int tint_symbol_10[3][4] = {tint_symbol_8, tint_symbol_9, nonempty}; const int tint_symbol_10[3][4] = {tint_symbol_8, tint_symbol_9, nonempty};
const int nested_nonempty_with_expr[2][3][4] = {tint_symbol_10, nested_nonempty[1]}; const int nested_nonempty_with_expr[2][3][4] = {tint_symbol_10, nested_nonempty[1]};
const int tint_symbol_11[4] = (int[4])0; const int tint_symbol_11[4] = (int[4])0;
const int subexpr_empty = tint_symbol_11[1]; const int subexpr_empty = 0;
const int tint_symbol_12[4] = {1, 2, 3, 4}; const int tint_symbol_12[4] = {1, 2, 3, 4};
const int subexpr_nonempty = tint_symbol_12[2]; const int subexpr_nonempty = 3;
const int tint_symbol_13[4] = {1, 42, (42 + 1), nonempty[3]}; const int tint_symbol_13[4] = {1, 42, (42 + 1), 4};
const int subexpr_nonempty_with_expr = tint_symbol_13[2]; const int subexpr_nonempty_with_expr = tint_symbol_13[2];
const int tint_symbol_14[2][4] = (int[2][4])0; const int tint_symbol_14[2][4] = (int[2][4])0;
const int subexpr_nested_empty[4] = tint_symbol_14[1]; const int subexpr_nested_empty[4] = tint_symbol_14[1];
@ -30,7 +30,7 @@ void main() {
const int tint_symbol_16[4] = {5, 6, 7, 8}; const int tint_symbol_16[4] = {5, 6, 7, 8};
const int tint_symbol_17[2][4] = {tint_symbol_15, tint_symbol_16}; const int tint_symbol_17[2][4] = {tint_symbol_15, tint_symbol_16};
const int subexpr_nested_nonempty[4] = tint_symbol_17[1]; const int subexpr_nested_nonempty[4] = tint_symbol_17[1];
const int tint_symbol_18[4] = {1, 42, (42 + 1), nonempty[3]}; const int tint_symbol_18[4] = {1, 42, (42 + 1), 4};
const int tint_symbol_19[2][4] = {tint_symbol_18, nested_nonempty[1][2]}; const int tint_symbol_19[2][4] = {tint_symbol_18, nested_nonempty[1][2]};
const int subexpr_nested_nonempty_with_expr[4] = tint_symbol_19[1]; const int subexpr_nested_nonempty_with_expr[4] = tint_symbol_19[1];
return; return;

View File

@ -1,7 +1,7 @@
; SPIR-V ; SPIR-V
; Version: 1.3 ; Version: 1.3
; Generator: Google Tint Compiler; 0 ; Generator: Google Tint Compiler; 0
; Bound: 79 ; Bound: 66
; Schema: 0 ; Schema: 0
OpCapability Shader OpCapability Shader
OpMemoryModel Logical GLSL450 OpMemoryModel Logical GLSL450
@ -29,66 +29,53 @@
%_arr__arr_int_uint_4_uint_3 = OpTypeArray %_arr_int_uint_4 %uint_3 %_arr__arr_int_uint_4_uint_3 = OpTypeArray %_arr_int_uint_4 %uint_3
%uint_2 = OpConstant %uint 2 %uint_2 = OpConstant %uint 2
%_arr__arr__arr_int_uint_4_uint_3_uint_2 = OpTypeArray %_arr__arr_int_uint_4_uint_3 %uint_2 %_arr__arr__arr_int_uint_4_uint_3_uint_2 = OpTypeArray %_arr__arr_int_uint_4_uint_3 %uint_2
%23 = OpConstantNull %_arr__arr__arr_int_uint_4_uint_3_uint_2 %22 = OpConstantNull %_arr__arr__arr_int_uint_4_uint_3_uint_2
%int_5 = OpConstant %int 5 %int_5 = OpConstant %int 5
%int_6 = OpConstant %int 6 %int_6 = OpConstant %int 6
%int_7 = OpConstant %int 7 %int_7 = OpConstant %int 7
%int_8 = OpConstant %int 8 %int_8 = OpConstant %int 8
%28 = OpConstantComposite %_arr_int_uint_4 %int_5 %int_6 %int_7 %int_8 %27 = OpConstantComposite %_arr_int_uint_4 %int_5 %int_6 %int_7 %int_8
%int_9 = OpConstant %int 9 %int_9 = OpConstant %int 9
%int_10 = OpConstant %int 10 %int_10 = OpConstant %int 10
%int_11 = OpConstant %int 11 %int_11 = OpConstant %int 11
%int_12 = OpConstant %int 12 %int_12 = OpConstant %int 12
%33 = OpConstantComposite %_arr_int_uint_4 %int_9 %int_10 %int_11 %int_12 %32 = OpConstantComposite %_arr_int_uint_4 %int_9 %int_10 %int_11 %int_12
%34 = OpConstantComposite %_arr__arr_int_uint_4_uint_3 %15 %28 %33 %33 = OpConstantComposite %_arr__arr_int_uint_4_uint_3 %15 %27 %32
%int_13 = OpConstant %int 13 %int_13 = OpConstant %int 13
%int_14 = OpConstant %int 14 %int_14 = OpConstant %int 14
%int_15 = OpConstant %int 15 %int_15 = OpConstant %int 15
%int_16 = OpConstant %int 16 %int_16 = OpConstant %int 16
%39 = OpConstantComposite %_arr_int_uint_4 %int_13 %int_14 %int_15 %int_16 %38 = OpConstantComposite %_arr_int_uint_4 %int_13 %int_14 %int_15 %int_16
%int_17 = OpConstant %int 17 %int_17 = OpConstant %int 17
%int_18 = OpConstant %int 18 %int_18 = OpConstant %int 18
%int_19 = OpConstant %int 19 %int_19 = OpConstant %int 19
%int_20 = OpConstant %int 20 %int_20 = OpConstant %int 20
%44 = OpConstantComposite %_arr_int_uint_4 %int_17 %int_18 %int_19 %int_20 %43 = OpConstantComposite %_arr_int_uint_4 %int_17 %int_18 %int_19 %int_20
%int_21 = OpConstant %int 21 %int_21 = OpConstant %int 21
%int_22 = OpConstant %int 22 %int_22 = OpConstant %int 22
%int_23 = OpConstant %int 23 %int_23 = OpConstant %int 23
%int_24 = OpConstant %int 24 %int_24 = OpConstant %int 24
%49 = OpConstantComposite %_arr_int_uint_4 %int_21 %int_22 %int_23 %int_24 %48 = OpConstantComposite %_arr_int_uint_4 %int_21 %int_22 %int_23 %int_24
%50 = OpConstantComposite %_arr__arr_int_uint_4_uint_3 %39 %44 %49 %49 = OpConstantComposite %_arr__arr_int_uint_4_uint_3 %38 %43 %48
%51 = OpConstantComposite %_arr__arr__arr_int_uint_4_uint_3_uint_2 %34 %50 %50 = OpConstantComposite %_arr__arr__arr_int_uint_4_uint_3_uint_2 %33 %49
%57 = OpConstantNull %int
%_arr__arr_int_uint_4_uint_2 = OpTypeArray %_arr_int_uint_4 %uint_2 %_arr__arr_int_uint_4_uint_2 = OpTypeArray %_arr_int_uint_4 %uint_2
%68 = OpConstantNull %_arr__arr_int_uint_4_uint_2
%70 = OpConstantComposite %_arr__arr_int_uint_4_uint_2 %15 %28
%main = OpFunction %void None %1 %main = OpFunction %void None %1
%4 = OpLabel %4 = OpLabel
%16 = OpIAdd %int %int_42 %int_1 %16 = OpIAdd %int %int_42 %int_1
%17 = OpCompositeExtract %int %15 3 %17 = OpCompositeConstruct %_arr_int_uint_4 %int_1 %int_42 %16 %int_4
%18 = OpCompositeConstruct %_arr_int_uint_4 %int_1 %int_42 %16 %17 %51 = OpIAdd %int %int_42 %int_1
%52 = OpIAdd %int %int_42 %int_1 %52 = OpCompositeConstruct %_arr_int_uint_4 %int_1 %int_2 %int_42 %51
%53 = OpCompositeConstruct %_arr_int_uint_4 %int_1 %int_2 %int_42 %52 %53 = OpIAdd %int %int_4 %int_1
%54 = OpCompositeExtract %int %15 2 %54 = OpCompositeConstruct %_arr_int_uint_4 %int_5 %int_6 %int_3 %53
%55 = OpCompositeExtract %int %15 3 %55 = OpCompositeConstruct %_arr__arr_int_uint_4_uint_3 %52 %54 %15
%56 = OpIAdd %int %55 %int_1 %56 = OpCompositeConstruct %_arr__arr__arr_int_uint_4_uint_3_uint_2 %55 %49
%57 = OpCompositeConstruct %_arr_int_uint_4 %int_5 %int_6 %54 %56 %58 = OpIAdd %int %int_42 %int_1
%58 = OpCompositeConstruct %_arr__arr_int_uint_4_uint_3 %53 %57 %15 %59 = OpCompositeConstruct %_arr_int_uint_4 %int_1 %int_42 %58 %int_4
%59 = OpCompositeExtract %_arr__arr_int_uint_4_uint_3 %51 1 %60 = OpCompositeExtract %int %59 2
%60 = OpCompositeConstruct %_arr__arr__arr_int_uint_4_uint_3_uint_2 %58 %59 %62 = OpIAdd %int %int_42 %int_1
%61 = OpCompositeExtract %int %10 1 %63 = OpCompositeConstruct %_arr_int_uint_4 %int_1 %int_42 %62 %int_4
%62 = OpCompositeExtract %int %15 2 %64 = OpCompositeConstruct %_arr__arr_int_uint_4_uint_2 %63 %48
%63 = OpIAdd %int %int_42 %int_1 %65 = OpCompositeExtract %_arr_int_uint_4 %64 1
%64 = OpCompositeExtract %int %15 3
%65 = OpCompositeConstruct %_arr_int_uint_4 %int_1 %int_42 %63 %64
%66 = OpCompositeExtract %int %65 2
%69 = OpCompositeExtract %_arr_int_uint_4 %68 1
%71 = OpCompositeExtract %_arr_int_uint_4 %70 1
%72 = OpIAdd %int %int_42 %int_1
%73 = OpCompositeExtract %int %15 3
%74 = OpCompositeConstruct %_arr_int_uint_4 %int_1 %int_42 %72 %73
%75 = OpCompositeExtract %_arr__arr_int_uint_4_uint_3 %51 1
%76 = OpCompositeExtract %_arr_int_uint_4 %75 2
%77 = OpCompositeConstruct %_arr__arr_int_uint_4_uint_2 %74 %76
%78 = OpCompositeExtract %_arr_int_uint_4 %77 1
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,6 @@ void unused_entry_point() {
} }
int f() { int f() {
int a[8] = int[8](1, 2, 3, 4, 5, 6, 7, 8); int a[8] = int[8](1, 2, 3, 4, 5, 6, 7, 8);
return a[1]; return 2;
} }

View File

@ -5,5 +5,5 @@ void unused_entry_point() {
int f() { int f() {
const int a[8] = {1, 2, 3, 4, 5, 6, 7, 8}; const int a[8] = {1, 2, 3, 4, 5, 6, 7, 8};
return a[1]; return 2;
} }

View File

@ -1,7 +1,7 @@
; SPIR-V ; SPIR-V
; Version: 1.3 ; Version: 1.3
; Generator: Google Tint Compiler; 0 ; Generator: Google Tint Compiler; 0
; Bound: 22 ; Bound: 21
; Schema: 0 ; Schema: 0
OpCapability Shader OpCapability Shader
OpMemoryModel Logical GLSL450 OpMemoryModel Logical GLSL450
@ -32,6 +32,5 @@
OpFunctionEnd OpFunctionEnd
%f = OpFunction %int None %5 %f = OpFunction %int None %5
%8 = OpLabel %8 = OpLabel
%21 = OpCompositeExtract %int %20 1 OpReturnValue %int_2
OpReturnValue %21
OpFunctionEnd OpFunctionEnd

View File

@ -6,6 +6,6 @@ void unused_entry_point() {
} }
int f() { int f() {
int a[8] = int[8](1, 2, 3, 4, 5, 6, 7, 8); int a[8] = int[8](1, 2, 3, 4, 5, 6, 7, 8);
return a[1]; return 2;
} }

View File

@ -5,5 +5,5 @@ void unused_entry_point() {
int f() { int f() {
const int a[8] = {1, 2, 3, 4, 5, 6, 7, 8}; const int a[8] = {1, 2, 3, 4, 5, 6, 7, 8};
return a[1]; return 2;
} }

View File

@ -1,7 +1,7 @@
; SPIR-V ; SPIR-V
; Version: 1.3 ; Version: 1.3
; Generator: Google Tint Compiler; 0 ; Generator: Google Tint Compiler; 0
; Bound: 22 ; Bound: 21
; Schema: 0 ; Schema: 0
OpCapability Shader OpCapability Shader
OpMemoryModel Logical GLSL450 OpMemoryModel Logical GLSL450
@ -32,6 +32,5 @@
OpFunctionEnd OpFunctionEnd
%f = OpFunction %int None %5 %f = OpFunction %int None %5
%8 = OpLabel %8 = OpLabel
%21 = OpCompositeExtract %int %20 1 OpReturnValue %int_2
OpReturnValue %21
OpFunctionEnd OpFunctionEnd

View File

@ -8,7 +8,7 @@ void f() {
int i = 0; int i = 0;
while (true) { while (true) {
int tint_symbol[1] = int[1](1); int tint_symbol[1] = int[1](1);
if (!((i < tint_symbol[0]))) { if (!((i < 1))) {
break; break;
} }
{ {

View File

@ -7,7 +7,7 @@ void f() {
int i = 0; int i = 0;
[loop] while (true) { [loop] while (true) {
const int tint_symbol[1] = {1}; const int tint_symbol[1] = {1};
if (!((i < tint_symbol[0]))) { if (!((i < 1))) {
break; break;
} }
{ {

View File

@ -1,7 +1,7 @@
; SPIR-V ; SPIR-V
; Version: 1.3 ; Version: 1.3
; Generator: Google Tint Compiler; 0 ; Generator: Google Tint Compiler; 0
; Bound: 27 ; Bound: 22
; Schema: 0 ; Schema: 0
OpCapability Shader OpCapability Shader
OpMemoryModel Logical GLSL450 OpMemoryModel Logical GLSL450
@ -10,17 +10,12 @@
OpName %unused_entry_point "unused_entry_point" OpName %unused_entry_point "unused_entry_point"
OpName %f "f" OpName %f "f"
OpName %i "i" OpName %i "i"
OpDecorate %_arr_int_uint_1 ArrayStride 4
%void = OpTypeVoid %void = OpTypeVoid
%1 = OpTypeFunction %void %1 = OpTypeFunction %void
%int = OpTypeInt 32 1 %int = OpTypeInt 32 1
%_ptr_Function_int = OpTypePointer Function %int %_ptr_Function_int = OpTypePointer Function %int
%10 = OpConstantNull %int %10 = OpConstantNull %int
%uint = OpTypeInt 32 0
%uint_1 = OpConstant %uint 1
%_arr_int_uint_1 = OpTypeArray %int %uint_1
%int_1 = OpConstant %int 1 %int_1 = OpConstant %int 1
%21 = OpConstantComposite %_arr_int_uint_1 %int_1
%bool = OpTypeBool %bool = OpTypeBool
%unused_entry_point = OpFunction %void None %1 %unused_entry_point = OpFunction %void None %1
%4 = OpLabel %4 = OpLabel
@ -35,14 +30,13 @@
OpBranch %14 OpBranch %14
%14 = OpLabel %14 = OpLabel
%16 = OpLoad %int %i %16 = OpLoad %int %i
%22 = OpCompositeExtract %int %21 0 %18 = OpSLessThan %bool %16 %int_1
%23 = OpSLessThan %bool %16 %22 %15 = OpLogicalNot %bool %18
%15 = OpLogicalNot %bool %23 OpSelectionMerge %20 None
OpSelectionMerge %25 None OpBranchConditional %15 %21 %20
OpBranchConditional %15 %26 %25 %21 = OpLabel
%26 = OpLabel
OpBranch %12 OpBranch %12
%25 = OpLabel %20 = OpLabel
OpBranch %13 OpBranch %13
%13 = OpLabel %13 = OpLabel
OpBranch %11 OpBranch %11

View File

@ -14,7 +14,7 @@ void f() {
} }
{ {
int tint_symbol[1] = int[1](1); int tint_symbol[1] = int[1](1);
i = (i + tint_symbol[0]); i = (i + 1);
} }
} }
} }

View File

@ -13,7 +13,7 @@ void f() {
} }
{ {
const int tint_symbol[1] = {1}; const int tint_symbol[1] = {1};
i = (i + tint_symbol[0]); i = (i + 1);
} }
} }
} }

View File

@ -1,7 +1,7 @@
; SPIR-V ; SPIR-V
; Version: 1.3 ; Version: 1.3
; Generator: Google Tint Compiler; 0 ; Generator: Google Tint Compiler; 0
; Bound: 28 ; Bound: 23
; Schema: 0 ; Schema: 0
OpCapability Shader OpCapability Shader
OpMemoryModel Logical GLSL450 OpMemoryModel Logical GLSL450
@ -10,7 +10,6 @@
OpName %unused_entry_point "unused_entry_point" OpName %unused_entry_point "unused_entry_point"
OpName %f "f" OpName %f "f"
OpName %i "i" OpName %i "i"
OpDecorate %_arr_int_uint_1 ArrayStride 4
%void = OpTypeVoid %void = OpTypeVoid
%1 = OpTypeFunction %void %1 = OpTypeFunction %void
%int = OpTypeInt 32 1 %int = OpTypeInt 32 1
@ -18,11 +17,7 @@
%10 = OpConstantNull %int %10 = OpConstantNull %int
%bool = OpTypeBool %bool = OpTypeBool
%17 = OpConstantNull %bool %17 = OpConstantNull %bool
%uint = OpTypeInt 32 0
%uint_1 = OpConstant %uint 1
%_arr_int_uint_1 = OpTypeArray %int %uint_1
%int_1 = OpConstant %int 1 %int_1 = OpConstant %int 1
%25 = OpConstantComposite %_arr_int_uint_1 %int_1
%unused_entry_point = OpFunction %void None %1 %unused_entry_point = OpFunction %void None %1
%4 = OpLabel %4 = OpLabel
OpReturn OpReturn
@ -44,9 +39,8 @@
OpBranch %13 OpBranch %13
%13 = OpLabel %13 = OpLabel
%20 = OpLoad %int %i %20 = OpLoad %int %i
%26 = OpCompositeExtract %int %25 0 %22 = OpIAdd %int %20 %int_1
%27 = OpIAdd %int %20 %26 OpStore %i %22
OpStore %i %27
OpBranch %11 OpBranch %11
%12 = OpLabel %12 = OpLabel
OpReturn OpReturn

View File

@ -7,7 +7,7 @@ void unused_entry_point() {
void f() { void f() {
int tint_symbol[1] = int[1](1); int tint_symbol[1] = int[1](1);
{ {
for(int i = tint_symbol[0]; false; ) { for(int i = 1; false; ) {
} }
} }
} }

View File

@ -6,7 +6,7 @@ void unused_entry_point() {
void f() { void f() {
const int tint_symbol[1] = {1}; const int tint_symbol[1] = {1};
{ {
[loop] for(int i = tint_symbol[0]; false; ) { [loop] for(int i = 1; false; ) {
} }
} }
} }

View File

@ -1,7 +1,7 @@
; SPIR-V ; SPIR-V
; Version: 1.3 ; Version: 1.3
; Generator: Google Tint Compiler; 0 ; Generator: Google Tint Compiler; 0
; Bound: 26 ; Bound: 21
; Schema: 0 ; Schema: 0
OpCapability Shader OpCapability Shader
OpMemoryModel Logical GLSL450 OpMemoryModel Logical GLSL450
@ -10,42 +10,36 @@
OpName %unused_entry_point "unused_entry_point" OpName %unused_entry_point "unused_entry_point"
OpName %f "f" OpName %f "f"
OpName %i "i" OpName %i "i"
OpDecorate %_arr_int_uint_1 ArrayStride 4
%void = OpTypeVoid %void = OpTypeVoid
%1 = OpTypeFunction %void %1 = OpTypeFunction %void
%int = OpTypeInt 32 1 %int = OpTypeInt 32 1
%uint = OpTypeInt 32 0
%uint_1 = OpConstant %uint 1
%_arr_int_uint_1 = OpTypeArray %int %uint_1
%int_1 = OpConstant %int 1 %int_1 = OpConstant %int 1
%12 = OpConstantComposite %_arr_int_uint_1 %int_1
%13 = OpConstantNull %int
%_ptr_Function_int = OpTypePointer Function %int %_ptr_Function_int = OpTypePointer Function %int
%11 = OpConstantNull %int
%bool = OpTypeBool %bool = OpTypeBool
%23 = OpConstantNull %bool %18 = OpConstantNull %bool
%unused_entry_point = OpFunction %void None %1 %unused_entry_point = OpFunction %void None %1
%4 = OpLabel %4 = OpLabel
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd
%f = OpFunction %void None %1 %f = OpFunction %void None %1
%6 = OpLabel %6 = OpLabel
%i = OpVariable %_ptr_Function_int Function %13 %i = OpVariable %_ptr_Function_int Function %11
%14 = OpCompositeExtract %int %12 0 OpStore %i %int_1
OpStore %i %14 OpBranch %12
OpBranch %17 %12 = OpLabel
%17 = OpLabel OpLoopMerge %13 %14 None
OpLoopMerge %18 %19 None OpBranch %15
OpBranch %20 %15 = OpLabel
%16 = OpLogicalNot %bool %18
OpSelectionMerge %19 None
OpBranchConditional %16 %20 %19
%20 = OpLabel %20 = OpLabel
%21 = OpLogicalNot %bool %23 OpBranch %13
OpSelectionMerge %24 None
OpBranchConditional %21 %25 %24
%25 = OpLabel
OpBranch %18
%24 = OpLabel
OpBranch %19
%19 = OpLabel %19 = OpLabel
OpBranch %17 OpBranch %14
%18 = OpLabel %14 = OpLabel
OpBranch %12
%13 = OpLabel
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd