Moved sem::ArrayCount to an inherited structure

This CL moves the ArrayCount from a variant to use inheritance. This
will allow the sem to have different array count classes from the IR.
The ArrayCounts, similar to types, are unique across the code base and
are provided by the TypeManager.

Bug: tint:1718
Change-Id: Ib9c7c9df881e7a34cc3def2ff29571f536d66244
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/112441
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
dan sinclair
2022-12-01 23:45:18 +00:00
committed by Dawn LUCI CQ
parent 71e6bcf1af
commit 4b1d79e292
26 changed files with 439 additions and 302 deletions

View File

@@ -1321,7 +1321,6 @@ TEST_F(ResolverConstEvalTest, Array_i32_Zero) {
auto* arr = sem->Type()->As<sem::Array>();
ASSERT_NE(arr, nullptr);
EXPECT_TRUE(arr->ElemType()->Is<sem::I32>());
EXPECT_EQ(arr->Count(), sem::ConstantArrayCount{4u});
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
@@ -1359,7 +1358,6 @@ TEST_F(ResolverConstEvalTest, Array_f32_Zero) {
auto* arr = sem->Type()->As<sem::Array>();
ASSERT_NE(arr, nullptr);
EXPECT_TRUE(arr->ElemType()->Is<sem::F32>());
EXPECT_EQ(arr->Count(), sem::ConstantArrayCount{4u});
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
@@ -1397,7 +1395,6 @@ TEST_F(ResolverConstEvalTest, Array_vec3_f32_Zero) {
auto* arr = sem->Type()->As<sem::Array>();
ASSERT_NE(arr, nullptr);
EXPECT_TRUE(arr->ElemType()->Is<sem::Vector>());
EXPECT_EQ(arr->Count(), sem::ConstantArrayCount{2u});
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
@@ -1449,7 +1446,6 @@ TEST_F(ResolverConstEvalTest, Array_Struct_f32_Zero) {
auto* arr = sem->Type()->As<sem::Array>();
ASSERT_NE(arr, nullptr);
EXPECT_TRUE(arr->ElemType()->Is<sem::Struct>());
EXPECT_EQ(arr->Count(), sem::ConstantArrayCount{2u});
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue()->AllEqual());
EXPECT_TRUE(sem->ConstantValue()->AnyZero());
@@ -1487,7 +1483,6 @@ TEST_F(ResolverConstEvalTest, Array_i32_Elements) {
auto* arr = sem->Type()->As<sem::Array>();
ASSERT_NE(arr, nullptr);
EXPECT_TRUE(arr->ElemType()->Is<sem::I32>());
EXPECT_EQ(arr->Count(), sem::ConstantArrayCount{4u});
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
@@ -1525,7 +1520,6 @@ TEST_F(ResolverConstEvalTest, Array_f32_Elements) {
auto* arr = sem->Type()->As<sem::Array>();
ASSERT_NE(arr, nullptr);
EXPECT_TRUE(arr->ElemType()->Is<sem::F32>());
EXPECT_EQ(arr->Count(), sem::ConstantArrayCount{4u});
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
@@ -1564,7 +1558,6 @@ TEST_F(ResolverConstEvalTest, Array_vec3_f32_Elements) {
auto* arr = sem->Type()->As<sem::Array>();
ASSERT_NE(arr, nullptr);
EXPECT_TRUE(arr->ElemType()->Is<sem::Vector>());
EXPECT_EQ(arr->Count(), sem::ConstantArrayCount{2u});
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());
@@ -1594,7 +1587,6 @@ TEST_F(ResolverConstEvalTest, Array_Struct_f32_Elements) {
auto* arr = sem->Type()->As<sem::Array>();
ASSERT_NE(arr, nullptr);
EXPECT_TRUE(arr->ElemType()->Is<sem::Struct>());
EXPECT_EQ(arr->Count(), sem::ConstantArrayCount{2u});
EXPECT_TYPE(sem->ConstantValue()->Type(), sem->Type());
EXPECT_FALSE(sem->ConstantValue()->AllEqual());
EXPECT_FALSE(sem->ConstantValue()->AnyZero());

View File

@@ -135,8 +135,8 @@ INSTANTIATE_TEST_SUITE_P(ResolverTest, ResolverInferredTypeParamTest, testing::V
TEST_F(ResolverInferredTypeTest, InferArray_Pass) {
auto* type = ty.array(ty.u32(), 10_u);
auto* expected_type =
create<sem::Array>(create<sem::U32>(), sem::ConstantArrayCount{10u}, 4u, 4u * 10u, 4u, 4u);
auto* expected_type = create<sem::Array>(
create<sem::U32>(), create<sem::ConstantArrayCount>(10u), 4u, 4u * 10u, 4u, 4u);
auto* ctor_expr = Construct(type);
auto* var = Var("a", ast::AddressSpace::kFunction, ctor_expr);

View File

@@ -532,12 +532,13 @@ bool match_array(MatchState&, const sem::Type* ty, const sem::Type*& T) {
}
const sem::Array* build_array(MatchState& state, const sem::Type* el) {
return state.builder.create<sem::Array>(el,
/* count */ sem::RuntimeArrayCount{},
/* align */ 0u,
/* size */ 0u,
/* stride */ 0u,
/* stride_implicit */ 0u);
return state.builder.create<sem::Array>(
el,
/* count */ state.builder.create<sem::RuntimeArrayCount>(),
/* align */ 0u,
/* size */ 0u,
/* stride */ 0u,
/* stride_implicit */ 0u);
}
bool match_ptr(MatchState&, const sem::Type* ty, Number& S, const sem::Type*& T, Number& A) {

View File

@@ -252,7 +252,8 @@ TEST_F(IntrinsicTableTest, MismatchPointer) {
}
TEST_F(IntrinsicTableTest, MatchArray) {
auto* arr = create<sem::Array>(create<sem::U32>(), sem::RuntimeArrayCount{}, 4u, 4u, 4u, 4u);
auto* arr =
create<sem::Array>(create<sem::U32>(), create<sem::RuntimeArrayCount>(), 4u, 4u, 4u, 4u);
auto* arr_ptr = create<sem::Pointer>(arr, ast::AddressSpace::kStorage, ast::Access::kReadWrite);
auto result = table->Lookup(BuiltinType::kArrayLength, utils::Vector{arr_ptr},
sem::EvaluationStage::kConstant, Source{});
@@ -955,7 +956,8 @@ TEST_F(IntrinsicTableTest, MatchTypeConversion) {
}
TEST_F(IntrinsicTableTest, MismatchTypeConversion) {
auto* arr = create<sem::Array>(create<sem::U32>(), sem::RuntimeArrayCount{}, 4u, 4u, 4u, 4u);
auto* arr =
create<sem::Array>(create<sem::U32>(), create<sem::RuntimeArrayCount>(), 4u, 4u, 4u, 4u);
auto* f32 = create<sem::F32>();
auto result = table->Lookup(InitConvIntrinsic::kVec3, f32, utils::Vector{arr},
sem::EvaluationStage::kConstant, Source{{12, 34}});

View File

@@ -106,13 +106,14 @@ TEST_F(ResolverIsHostShareable, Atomic) {
}
TEST_F(ResolverIsHostShareable, ArraySizedOfHostShareable) {
auto* arr =
create<sem::Array>(create<sem::I32>(), sem::ConstantArrayCount{5u}, 4u, 20u, 4u, 4u);
auto* arr = create<sem::Array>(create<sem::I32>(), create<sem::ConstantArrayCount>(5u), 4u, 20u,
4u, 4u);
EXPECT_TRUE(r()->IsHostShareable(arr));
}
TEST_F(ResolverIsHostShareable, ArrayUnsizedOfHostShareable) {
auto* arr = create<sem::Array>(create<sem::I32>(), sem::RuntimeArrayCount{}, 4u, 4u, 4u, 4u);
auto* arr =
create<sem::Array>(create<sem::I32>(), create<sem::RuntimeArrayCount>(), 4u, 4u, 4u, 4u);
EXPECT_TRUE(r()->IsHostShareable(arr));
}

View File

@@ -89,13 +89,14 @@ TEST_F(ResolverIsStorableTest, Atomic) {
}
TEST_F(ResolverIsStorableTest, ArraySizedOfStorable) {
auto* arr =
create<sem::Array>(create<sem::I32>(), sem::ConstantArrayCount{5u}, 4u, 20u, 4u, 4u);
auto* arr = create<sem::Array>(create<sem::I32>(), create<sem::ConstantArrayCount>(5u), 4u, 20u,
4u, 4u);
EXPECT_TRUE(r()->IsStorable(arr));
}
TEST_F(ResolverIsStorableTest, ArrayUnsizedOfStorable) {
auto* arr = create<sem::Array>(create<sem::I32>(), sem::RuntimeArrayCount{}, 4u, 4u, 4u, 4u);
auto* arr =
create<sem::Array>(create<sem::I32>(), create<sem::RuntimeArrayCount>(), 4u, 4u, 4u, 4u);
EXPECT_TRUE(r()->IsStorable(arr));
}

View File

@@ -2143,8 +2143,7 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
[&](const ast::Array* a) -> sem::Call* {
Mark(a);
// array element type must be inferred if it was not specified.
sem::ArrayCount el_count =
sem::ConstantArrayCount{static_cast<uint32_t>(args.Length())};
const sem::ArrayCount* el_count = nullptr;
const sem::Type* el_ty = nullptr;
if (a->type) {
el_ty = Type(a->type);
@@ -2155,14 +2154,15 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
AddError("cannot construct a runtime-sized array", expr->source);
return nullptr;
}
if (auto count = ArrayCount(a->count)) {
el_count = count.Get();
} else {
el_count = ArrayCount(a->count);
if (!el_count) {
return nullptr;
}
// Note: validation later will detect any mismatches between explicit array
// size and number of initializer expressions.
} else {
el_count = builder_->create<sem::ConstantArrayCount>(
static_cast<uint32_t>(args.Length()));
auto arg_tys =
utils::Transform(args, [](auto* arg) { return arg->Type()->UnwrapRef(); });
el_ty = sem::Type::Common(arg_tys);
@@ -2936,15 +2936,16 @@ sem::Array* Resolver::Array(const ast::Array* arr) {
return nullptr;
}
sem::ArrayCount el_count = sem::RuntimeArrayCount{};
const sem::ArrayCount* el_count = nullptr;
// Evaluate the constant array count expression.
if (auto* count_expr = arr->count) {
if (auto count = ArrayCount(count_expr)) {
el_count = count.Get();
} else {
el_count = ArrayCount(count_expr);
if (!el_count) {
return nullptr;
}
} else {
el_count = builder_->create<sem::RuntimeArrayCount>();
}
auto* out = Array(arr->type->source, //
@@ -2971,11 +2972,11 @@ sem::Array* Resolver::Array(const ast::Array* arr) {
return out;
}
utils::Result<sem::ArrayCount> Resolver::ArrayCount(const ast::Expression* count_expr) {
const sem::ArrayCount* Resolver::ArrayCount(const ast::Expression* count_expr) {
// Evaluate the constant array count expression.
const auto* count_sem = Materialize(Expression(count_expr));
if (!count_sem) {
return utils::Failure;
return nullptr;
}
if (count_sem->Stage() == sem::EvaluationStage::kOverride) {
@@ -2983,34 +2984,34 @@ utils::Result<sem::ArrayCount> Resolver::ArrayCount(const ast::Expression* count
// Is the count a named 'override'?
if (auto* user = count_sem->UnwrapMaterialize()->As<sem::VariableUser>()) {
if (auto* global = user->Variable()->As<sem::GlobalVariable>()) {
return sem::ArrayCount{sem::NamedOverrideArrayCount{global}};
return builder_->create<sem::NamedOverrideArrayCount>(global);
}
}
return sem::ArrayCount{sem::UnnamedOverrideArrayCount{count_sem}};
return builder_->create<sem::UnnamedOverrideArrayCount>(count_sem);
}
auto* count_val = count_sem->ConstantValue();
if (!count_val) {
AddError("array count must evaluate to a constant integer expression or override variable",
count_expr->source);
return utils::Failure;
return nullptr;
}
if (auto* ty = count_val->Type(); !ty->is_integer_scalar()) {
AddError("array count must evaluate to a constant integer expression, but is type '" +
builder_->FriendlyName(ty) + "'",
count_expr->source);
return utils::Failure;
return nullptr;
}
int64_t count = count_val->As<AInt>();
if (count < 1) {
AddError("array count (" + std::to_string(count) + ") must be greater than 0",
count_expr->source);
return utils::Failure;
return nullptr;
}
return sem::ArrayCount{sem::ConstantArrayCount{static_cast<uint32_t>(count)}};
return builder_->create<sem::ConstantArrayCount>(static_cast<uint32_t>(count));
}
bool Resolver::ArrayAttributes(utils::VectorRef<const ast::Attribute*> attributes,
@@ -3046,7 +3047,7 @@ bool Resolver::ArrayAttributes(utils::VectorRef<const ast::Attribute*> attribute
sem::Array* Resolver::Array(const Source& el_source,
const Source& count_source,
const sem::Type* el_ty,
sem::ArrayCount el_count,
const sem::ArrayCount* el_count,
uint32_t explicit_stride) {
uint32_t el_align = el_ty->Align();
uint32_t el_size = el_ty->Size();
@@ -3054,7 +3055,7 @@ sem::Array* Resolver::Array(const Source& el_source,
uint64_t stride = explicit_stride ? explicit_stride : implicit_stride;
uint64_t size = 0;
if (auto const_count = std::get_if<sem::ConstantArrayCount>(&el_count)) {
if (auto const_count = el_count->As<sem::ConstantArrayCount>()) {
size = const_count->value * stride;
if (size > std::numeric_limits<uint32_t>::max()) {
std::stringstream msg;
@@ -3063,7 +3064,7 @@ sem::Array* Resolver::Array(const Source& el_source,
AddError(msg.str(), count_source);
return nullptr;
}
} else if (std::holds_alternative<sem::RuntimeArrayCount>(el_count)) {
} else if (el_count->Is<sem::RuntimeArrayCount>()) {
size = stride;
}
auto* out = builder_->create<sem::Array>(el_ty, el_count, el_align, static_cast<uint32_t>(size),

View File

@@ -273,7 +273,7 @@ class Resolver {
/// Resolves and validates the expression used as the count parameter of an array.
/// @param count_expr the expression used as the second template parameter to an array<>.
/// @returns the number of elements in the array.
utils::Result<sem::ArrayCount> ArrayCount(const ast::Expression* count_expr);
const sem::ArrayCount* ArrayCount(const ast::Expression* count_expr);
/// Resolves and validates the attributes on an array.
/// @param attributes the attributes on the array type.
@@ -296,7 +296,7 @@ class Resolver {
sem::Array* Array(const Source& el_source,
const Source& count_source,
const sem::Type* el_ty,
sem::ArrayCount el_count,
const sem::ArrayCount* el_count,
uint32_t explicit_stride);
/// Builds and returns the semantic information for the alias `alias`.

View File

@@ -440,7 +440,7 @@ TEST_F(ResolverTest, ArraySize_UnsignedLiteral) {
auto* ref = TypeOf(a)->As<sem::Reference>();
ASSERT_NE(ref, nullptr);
auto* ary = ref->StoreType()->As<sem::Array>();
EXPECT_EQ(ary->Count(), sem::ConstantArrayCount{10u});
EXPECT_EQ(ary->Count(), create<sem::ConstantArrayCount>(10u));
}
TEST_F(ResolverTest, ArraySize_SignedLiteral) {
@@ -453,7 +453,7 @@ TEST_F(ResolverTest, ArraySize_SignedLiteral) {
auto* ref = TypeOf(a)->As<sem::Reference>();
ASSERT_NE(ref, nullptr);
auto* ary = ref->StoreType()->As<sem::Array>();
EXPECT_EQ(ary->Count(), sem::ConstantArrayCount{10u});
EXPECT_EQ(ary->Count(), create<sem::ConstantArrayCount>(10u));
}
TEST_F(ResolverTest, ArraySize_UnsignedConst) {
@@ -468,7 +468,7 @@ TEST_F(ResolverTest, ArraySize_UnsignedConst) {
auto* ref = TypeOf(a)->As<sem::Reference>();
ASSERT_NE(ref, nullptr);
auto* ary = ref->StoreType()->As<sem::Array>();
EXPECT_EQ(ary->Count(), sem::ConstantArrayCount{10u});
EXPECT_EQ(ary->Count(), create<sem::ConstantArrayCount>(10u));
}
TEST_F(ResolverTest, ArraySize_SignedConst) {
@@ -483,7 +483,7 @@ TEST_F(ResolverTest, ArraySize_SignedConst) {
auto* ref = TypeOf(a)->As<sem::Reference>();
ASSERT_NE(ref, nullptr);
auto* ary = ref->StoreType()->As<sem::Array>();
EXPECT_EQ(ary->Count(), sem::ConstantArrayCount{10u});
EXPECT_EQ(ary->Count(), create<sem::ConstantArrayCount>(10u));
}
TEST_F(ResolverTest, ArraySize_NamedOverride) {
@@ -500,7 +500,7 @@ TEST_F(ResolverTest, ArraySize_NamedOverride) {
auto* ary = ref->StoreType()->As<sem::Array>();
auto* sem_override = Sem().Get<sem::GlobalVariable>(override);
ASSERT_NE(sem_override, nullptr);
EXPECT_EQ(ary->Count(), sem::NamedOverrideArrayCount{sem_override});
EXPECT_EQ(ary->Count(), create<sem::NamedOverrideArrayCount>(sem_override));
}
TEST_F(ResolverTest, ArraySize_NamedOverride_Equivalence) {
@@ -525,8 +525,8 @@ TEST_F(ResolverTest, ArraySize_NamedOverride_Equivalence) {
auto* sem_override = Sem().Get<sem::GlobalVariable>(override);
ASSERT_NE(sem_override, nullptr);
EXPECT_EQ(ary_a->Count(), sem::NamedOverrideArrayCount{sem_override});
EXPECT_EQ(ary_b->Count(), sem::NamedOverrideArrayCount{sem_override});
EXPECT_EQ(ary_a->Count(), create<sem::NamedOverrideArrayCount>(sem_override));
EXPECT_EQ(ary_b->Count(), create<sem::NamedOverrideArrayCount>(sem_override));
EXPECT_EQ(ary_a, ary_b);
}
@@ -545,7 +545,7 @@ TEST_F(ResolverTest, ArraySize_UnnamedOverride) {
auto* ary = ref->StoreType()->As<sem::Array>();
auto* sem_override = Sem().Get<sem::GlobalVariable>(override);
ASSERT_NE(sem_override, nullptr);
EXPECT_EQ(ary->Count(), sem::UnnamedOverrideArrayCount{Sem().Get(cnt)});
EXPECT_EQ(ary->Count(), create<sem::UnnamedOverrideArrayCount>(Sem().Get(cnt)));
}
TEST_F(ResolverTest, ArraySize_UnamedOverride_Equivalence) {
@@ -572,8 +572,8 @@ TEST_F(ResolverTest, ArraySize_UnamedOverride_Equivalence) {
auto* sem_override = Sem().Get<sem::GlobalVariable>(override);
ASSERT_NE(sem_override, nullptr);
EXPECT_EQ(ary_a->Count(), sem::UnnamedOverrideArrayCount{Sem().Get(a_cnt)});
EXPECT_EQ(ary_b->Count(), sem::UnnamedOverrideArrayCount{Sem().Get(b_cnt)});
EXPECT_EQ(ary_a->Count(), create<sem::UnnamedOverrideArrayCount>(Sem().Get(a_cnt)));
EXPECT_EQ(ary_b->Count(), create<sem::UnnamedOverrideArrayCount>(Sem().Get(b_cnt)));
EXPECT_NE(ary_a, ary_b);
}

View File

@@ -659,9 +659,11 @@ struct DataType<array<N, T>> {
/// @return the semantic array type
static inline const sem::Type* Sem(ProgramBuilder& b) {
auto* el = DataType<T>::Sem(b);
sem::ArrayCount count = sem::ConstantArrayCount{N};
const sem::ArrayCount* count = nullptr;
if (N == 0) {
count = sem::RuntimeArrayCount{};
count = b.create<sem::RuntimeArrayCount>();
} else {
count = b.create<sem::ConstantArrayCount>(N);
}
return b.create<sem::Array>(
/* element */ el,

View File

@@ -1778,7 +1778,12 @@ bool Validator::ArrayInitializer(const ast::CallExpression* ctor,
return false;
}
const auto count = std::get<sem::ConstantArrayCount>(array_type->Count()).value;
if (!array_type->IsConstantSized()) {
TINT_ICE(Resolver, diagnostics_) << "Invalid ArrayCount found";
return false;
}
const auto count = array_type->Count()->As<sem::ConstantArrayCount>()->value;
if (!values.IsEmpty() && (values.Length() != count)) {
std::string fm = values.Length() < count ? "few" : "many";
AddError("array initializer has too " + fm + " elements: expected " +

View File

@@ -89,13 +89,14 @@ TEST_F(ValidatorIsStorableTest, Atomic) {
}
TEST_F(ValidatorIsStorableTest, ArraySizedOfStorable) {
auto* arr =
create<sem::Array>(create<sem::I32>(), sem::ConstantArrayCount{5u}, 4u, 20u, 4u, 4u);
auto* arr = create<sem::Array>(create<sem::I32>(), create<sem::ConstantArrayCount>(5u), 4u, 20u,
4u, 4u);
EXPECT_TRUE(v()->IsStorable(arr));
}
TEST_F(ValidatorIsStorableTest, ArrayUnsizedOfStorable) {
auto* arr = create<sem::Array>(create<sem::I32>(), sem::RuntimeArrayCount{}, 4u, 4u, 4u, 4u);
auto* arr =
create<sem::Array>(create<sem::I32>(), create<sem::RuntimeArrayCount>(), 4u, 4u, 4u, 4u);
EXPECT_TRUE(v()->IsStorable(arr));
}