sem: Fold together sem::Array and sem::ArrayType

There's now no need to have both.
Removes a whole bunch of Sem().Get() smell, and simplifies the resolver.

Also fixes a long-standing issue where an array with an explicit, but equal-to-implicit-stride attribute would result in a different type to an array without the decoration.

Bug: tint:724
Fixed: tint:782
Change-Id: I0202459009cd45be427cdb621993a5a3b07ff51e
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/50301
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
Ben Clayton
2021-05-07 20:58:34 +00:00
committed by Commit Bot service account
parent 6732e8561c
commit 4cd5eea87e
62 changed files with 486 additions and 591 deletions

View File

@@ -42,7 +42,7 @@ ast::ArrayAccessorExpression* BoundArrayAccessors::Transform(
auto& diags = ctx->dst->Diagnostics();
auto* ret_type = ctx->src->Sem().Get(expr->array())->Type()->UnwrapAll();
if (!ret_type->Is<sem::ArrayType>() && !ret_type->Is<sem::Matrix>() &&
if (!ret_type->Is<sem::Array>() && !ret_type->Is<sem::Matrix>() &&
!ret_type->Is<sem::Vector>()) {
return nullptr;
}
@@ -52,10 +52,10 @@ ast::ArrayAccessorExpression* BoundArrayAccessors::Transform(
uint32_t size = 0;
bool is_vec = ret_type->Is<sem::Vector>();
bool is_arr = ret_type->Is<sem::ArrayType>();
bool is_arr = ret_type->Is<sem::Array>();
if (is_vec || is_arr) {
size = is_vec ? ret_type->As<sem::Vector>()->size()
: ret_type->As<sem::ArrayType>()->size();
: ret_type->As<sem::Array>()->Count();
} else {
// The row accessor would have been an embedded array accessor and already
// handled, so we just need to do columns here.

View File

@@ -77,8 +77,8 @@ Output CalculateArrayLength::Run(const Program* in, const DataMap&) {
// get_buffer_size_intrinsic() emits the function decorated with
// BufferSizeIntrinsic that is transformed by the HLSL writer into a call to
// [RW]ByteAddressBuffer.GetDimensions().
std::unordered_map<sem::Struct*, Symbol> buffer_size_intrinsics;
auto get_buffer_size_intrinsic = [&](sem::Struct* buffer_type) {
std::unordered_map<const sem::Struct*, Symbol> buffer_size_intrinsics;
auto get_buffer_size_intrinsic = [&](const sem::Struct* buffer_type) {
return utils::GetOrCreate(buffer_size_intrinsics, buffer_type, [&] {
auto name = ctx.dst->Sym();
auto* buffer_typename =

View File

@@ -175,8 +175,8 @@ std::unique_ptr<Offset> Mul(LHS&& lhs_, RHS&& rhs_) {
/// TypePair is a pair of types that can be used as a unordered map or set key.
struct TypePair {
sem::Type* first;
sem::Type* second;
sem::Type const* first;
sem::Type const* second;
bool operator==(const TypePair& rhs) const {
return first == rhs.first && second == rhs.second;
}
@@ -188,20 +188,20 @@ struct TypePair {
};
/// @returns the size in bytes of a scalar
uint32_t ScalarSize(sem::Type*) {
uint32_t ScalarSize(const sem::Type*) {
// TODO(bclayton): Assumes 32-bit elements
return 4;
}
/// @returns the numer of bytes between columns of the given matrix
uint32_t MatrixColumnStride(sem::Matrix* mat) {
uint32_t MatrixColumnStride(const sem::Matrix* mat) {
return ScalarSize(mat->type()) * ((mat->rows() == 2) ? 2 : 4);
}
/// @returns a DecomposeStorageAccess::Intrinsic decoration that can be applied
/// to a stub function to load the type `ty`.
DecomposeStorageAccess::Intrinsic* IntrinsicLoadFor(ProgramBuilder* builder,
sem::Type* ty) {
const sem::Type* ty) {
using Intrinsic = DecomposeStorageAccess::Intrinsic;
auto intrinsic = [builder](Intrinsic::Type type) {
@@ -260,7 +260,7 @@ DecomposeStorageAccess::Intrinsic* IntrinsicLoadFor(ProgramBuilder* builder,
/// @returns a DecomposeStorageAccess::Intrinsic decoration that can be applied
/// to a stub function to store the type `ty`.
DecomposeStorageAccess::Intrinsic* IntrinsicStoreFor(ProgramBuilder* builder,
sem::Type* ty) {
const sem::Type* ty) {
using Intrinsic = DecomposeStorageAccess::Intrinsic;
auto intrinsic = [builder](Intrinsic::Type type) {
@@ -331,7 +331,7 @@ void InsertGlobal(CloneContext& ctx,
}
/// @returns the unwrapped, user-declared constructed type of ty.
const ast::NamedType* ConstructedTypeOf(sem::Type* ty) {
const ast::NamedType* ConstructedTypeOf(const sem::Type* ty) {
while (true) {
if (auto* ptr = ty->As<sem::Pointer>()) {
ty = ptr->type();
@@ -350,7 +350,7 @@ const ast::NamedType* ConstructedTypeOf(sem::Type* ty) {
}
/// @returns the given type with all pointers and aliases removed.
sem::Type* UnwrapPtrAndAlias(sem::Type* ty) {
const sem::Type* UnwrapPtrAndAlias(const sem::Type* ty) {
return ty->UnwrapPtrIfNeeded()->UnwrapAliasIfNeeded()->UnwrapPtrIfNeeded();
}
@@ -358,7 +358,7 @@ sem::Type* UnwrapPtrAndAlias(sem::Type* ty) {
struct StorageBufferAccess {
sem::Expression const* var = nullptr; // Storage buffer variable
std::unique_ptr<Offset> offset; // The byte offset on var
sem::Type* type = nullptr; // The type of the access
sem::Type const* type = nullptr; // The type of the access
operator bool() const { return var; } // Returns true if valid
};
@@ -422,8 +422,8 @@ struct DecomposeStorageAccess::State {
/// @return the name of the function that performs the load
Symbol LoadFunc(CloneContext& ctx,
const ast::NamedType* insert_after,
sem::Type* buf_ty,
sem::Type* el_ty) {
const sem::Type* buf_ty,
const sem::Type* el_ty) {
return utils::GetOrCreate(load_funcs, TypePair{buf_ty, el_ty}, [&] {
auto* buf_ast_ty = CreateASTTypeFor(&ctx, buf_ty);
ast::VariableList params = {
@@ -458,13 +458,11 @@ struct DecomposeStorageAccess::State {
member->Type()->UnwrapAll());
values.emplace_back(ctx.dst->Call(load, "buffer", offset));
}
} else if (auto* arr_ty = el_ty->As<sem::ArrayType>()) {
auto& sem = ctx.src->Sem();
auto* arr = sem.Get(arr_ty);
for (uint32_t i = 0; i < arr_ty->size(); i++) {
} else if (auto* arr = el_ty->As<sem::Array>()) {
for (uint32_t i = 0; i < arr->Count(); i++) {
auto* offset = ctx.dst->Add("offset", arr->Stride() * i);
Symbol load = LoadFunc(ctx, insert_after, buf_ty,
arr_ty->type()->UnwrapAll());
arr->ElemType()->UnwrapAll());
values.emplace_back(ctx.dst->Call(load, "buffer", offset));
}
}
@@ -491,8 +489,8 @@ struct DecomposeStorageAccess::State {
/// @return the name of the function that performs the store
Symbol StoreFunc(CloneContext& ctx,
const ast::NamedType* insert_after,
sem::Type* buf_ty,
sem::Type* el_ty) {
const sem::Type* buf_ty,
const sem::Type* el_ty) {
return utils::GetOrCreate(store_funcs, TypePair{buf_ty, el_ty}, [&] {
auto* buf_ast_ty = CreateASTTypeFor(&ctx, buf_ty);
auto* el_ast_ty = CreateASTTypeFor(&ctx, el_ty);
@@ -533,14 +531,12 @@ struct DecomposeStorageAccess::State {
auto* call = ctx.dst->Call(store, "buffer", offset, access);
body.emplace_back(ctx.dst->create<ast::CallStatement>(call));
}
} else if (auto* arr_ty = el_ty->As<sem::ArrayType>()) {
auto& sem = ctx.src->Sem();
auto* arr = sem.Get(arr_ty);
for (uint32_t i = 0; i < arr_ty->size(); i++) {
} else if (auto* arr = el_ty->As<sem::Array>()) {
for (uint32_t i = 0; i < arr->Count(); i++) {
auto* offset = ctx.dst->Add("offset", arr->Stride() * i);
auto* access = ctx.dst->IndexAccessor("value", ctx.dst->Expr(i));
Symbol store = StoreFunc(ctx, insert_after, buf_ty,
arr_ty->type()->UnwrapAll());
arr->ElemType()->UnwrapAll());
auto* call = ctx.dst->Call(store, "buffer", offset, access);
body.emplace_back(ctx.dst->create<ast::CallStatement>(call));
}
@@ -689,14 +685,13 @@ Output DecomposeStorageAccess::Run(const Program* in, const DataMap&) {
if (auto* accessor = node->As<ast::ArrayAccessorExpression>()) {
if (auto access = state.TakeAccess(accessor->array())) {
// X[Y]
if (auto* arr_ty = access.type->As<sem::ArrayType>()) {
auto stride = sem.Get(arr_ty)->Stride();
auto offset = Mul(stride, accessor->idx_expr());
if (auto* arr = access.type->As<sem::Array>()) {
auto offset = Mul(arr->Stride(), accessor->idx_expr());
state.AddAccess(accessor,
{
access.var,
Add(std::move(access.offset), std::move(offset)),
arr_ty->type()->UnwrapAll(),
arr->ElemType()->UnwrapAll(),
});
continue;
}

View File

@@ -96,7 +96,7 @@ void Hlsl::PromoteInitializersToConstVar(CloneContext& ctx) const {
}
auto* src_ty = src_sem_expr->Type();
if (src_ty->IsAnyOf<sem::ArrayType, sem::Struct>()) {
if (src_ty->IsAnyOf<sem::Array, sem::Struct>()) {
// Create a new symbol for the constant
auto dst_symbol = ctx.dst->Sym();
// Clone the type

View File

@@ -230,7 +230,7 @@ void Spirv::HandleSampleMaskBuiltins(CloneContext& ctx) const {
// Use the same name as the old variable.
auto var_name = ctx.Clone(var->symbol());
// Use `array<u32, 1>` for the new variable.
auto type = ctx.dst->ty.array(ctx.dst->ty.u32(), 1u);
auto* type = ctx.dst->ty.array(ctx.dst->ty.u32(), 1u);
// Create the new variable.
auto* var_arr = ctx.dst->Var(var->source(), var_name, type,
var->declared_storage_class(), nullptr,

View File

@@ -95,10 +95,13 @@ ast::Type* Transform::CreateASTTypeFor(CloneContext* ctx, const sem::Type* ty) {
auto* el = CreateASTTypeFor(ctx, v->type());
return ctx->dst->create<ast::Vector>(el, v->size());
}
if (auto* a = ty->As<sem::ArrayType>()) {
auto* el = CreateASTTypeFor(ctx, a->type());
auto decos = ctx->Clone(a->decorations());
return ctx->dst->create<ast::Array>(el, a->size(), std::move(decos));
if (auto* a = ty->As<sem::Array>()) {
auto* el = CreateASTTypeFor(ctx, a->ElemType());
ast::DecorationList decos;
if (!a->IsStrideImplicit()) {
decos.emplace_back(ctx->dst->create<ast::StrideDecoration>(a->Stride()));
}
return ctx->dst->create<ast::Array>(el, a->Count(), std::move(decos));
}
if (auto* ac = ty->As<sem::AccessControl>()) {
auto* el = CreateASTTypeFor(ctx, ac->type());

View File

@@ -76,16 +76,23 @@ TEST_F(CreateASTTypeForTest, Vector) {
ASSERT_EQ(vec->As<ast::Vector>()->size(), 2u);
}
TEST_F(CreateASTTypeForTest, Array) {
TEST_F(CreateASTTypeForTest, ArrayImplicitStride) {
auto* arr = create([](ProgramBuilder& b) {
return b.create<sem::ArrayType>(b.create<sem::F32>(), 4,
ast::DecorationList{
b.create<ast::StrideDecoration>(32u),
});
return b.create<sem::Array>(b.create<sem::F32>(), 2, 4, 4, 32u, true);
});
ASSERT_TRUE(arr->Is<ast::Array>());
ASSERT_TRUE(arr->As<ast::Array>()->type()->Is<ast::F32>());
ASSERT_EQ(arr->As<ast::Array>()->size(), 4u);
ASSERT_EQ(arr->As<ast::Array>()->size(), 2u);
ASSERT_EQ(arr->As<ast::Array>()->decorations().size(), 0u);
}
TEST_F(CreateASTTypeForTest, ArrayNonImplicitStride) {
auto* arr = create([](ProgramBuilder& b) {
return b.create<sem::Array>(b.create<sem::F32>(), 2, 4, 4, 32u, false);
});
ASSERT_TRUE(arr->Is<ast::Array>());
ASSERT_TRUE(arr->As<ast::Array>()->type()->Is<ast::F32>());
ASSERT_EQ(arr->As<ast::Array>()->size(), 2u);
ASSERT_EQ(arr->As<ast::Array>()->decorations().size(), 1u);
ASSERT_TRUE(
arr->As<ast::Array>()->decorations()[0]->Is<ast::StrideDecoration>());
@@ -95,7 +102,6 @@ TEST_F(CreateASTTypeForTest, Array) {
->stride(),
32u);
}
TEST_F(CreateASTTypeForTest, AccessControl) {
auto* ac = create([](ProgramBuilder& b) {
auto* decl = b.Structure("S", {}, {});