Resolver: make IsConstructible non-recursive for arrays and struct members
Also fix cases of implicit conversions of bool to int when creating sem::Array. Bug: tint:917 Change-Id: I5392fb737efc410f039b4dbd96cffc5daa4fd3a2 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/58783 Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Antonio Maiorano <amaiorano@google.com> Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
701820b1f4
commit
68a6dd0073
|
@ -215,7 +215,7 @@ TEST_F(IntrinsicTableTest, MismatchPointer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IntrinsicTableTest, MatchArray) {
|
TEST_F(IntrinsicTableTest, MatchArray) {
|
||||||
auto* arr = create<sem::Array>(create<sem::U32>(), 0, 4, 4, 4, true);
|
auto* arr = create<sem::Array>(create<sem::U32>(), 0, 4, 4, 4, 4);
|
||||||
auto* arr_ptr = create<sem::Pointer>(arr, ast::StorageClass::kStorage,
|
auto* arr_ptr = create<sem::Pointer>(arr, ast::StorageClass::kStorage,
|
||||||
ast::Access::kReadWrite);
|
ast::Access::kReadWrite);
|
||||||
auto* result =
|
auto* result =
|
||||||
|
|
|
@ -142,7 +142,7 @@ INSTANTIATE_TEST_SUITE_P(ResolverTest,
|
||||||
TEST_F(ResolverInferredTypeTest, InferArray_Pass) {
|
TEST_F(ResolverInferredTypeTest, InferArray_Pass) {
|
||||||
auto* type = ty.array(ty.u32(), 10);
|
auto* type = ty.array(ty.u32(), 10);
|
||||||
auto* expected_type =
|
auto* expected_type =
|
||||||
create<sem::Array>(create<sem::U32>(), 10, 4, 4 * 10, 4, true);
|
create<sem::Array>(create<sem::U32>(), 10, 4, 4 * 10, 4, 4);
|
||||||
|
|
||||||
auto* ctor_expr = Construct(type);
|
auto* ctor_expr = Construct(type);
|
||||||
auto* var = Var("a", nullptr, ast::StorageClass::kFunction, ctor_expr);
|
auto* var = Var("a", nullptr, ast::StorageClass::kFunction, ctor_expr);
|
||||||
|
|
|
@ -99,12 +99,12 @@ TEST_F(ResolverIsHostShareable, Atomic) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverIsHostShareable, ArraySizedOfHostShareable) {
|
TEST_F(ResolverIsHostShareable, ArraySizedOfHostShareable) {
|
||||||
auto* arr = create<sem::Array>(create<sem::I32>(), 5, 4, 20, 4, true);
|
auto* arr = create<sem::Array>(create<sem::I32>(), 5, 4, 20, 4, 4);
|
||||||
EXPECT_TRUE(r()->IsHostShareable(arr));
|
EXPECT_TRUE(r()->IsHostShareable(arr));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverIsHostShareable, ArrayUnsizedOfHostShareable) {
|
TEST_F(ResolverIsHostShareable, ArrayUnsizedOfHostShareable) {
|
||||||
auto* arr = create<sem::Array>(create<sem::I32>(), 0, 4, 4, 4, true);
|
auto* arr = create<sem::Array>(create<sem::I32>(), 0, 4, 4, 4, 4);
|
||||||
EXPECT_TRUE(r()->IsHostShareable(arr));
|
EXPECT_TRUE(r()->IsHostShareable(arr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,12 +74,12 @@ TEST_F(ResolverIsStorableTest, Atomic) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverIsStorableTest, ArraySizedOfStorable) {
|
TEST_F(ResolverIsStorableTest, ArraySizedOfStorable) {
|
||||||
auto* arr = create<sem::Array>(create<sem::I32>(), 5, 4, 20, 4, true);
|
auto* arr = create<sem::Array>(create<sem::I32>(), 5, 4, 20, 4, 4);
|
||||||
EXPECT_TRUE(r()->IsStorable(arr));
|
EXPECT_TRUE(r()->IsStorable(arr));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverIsStorableTest, ArrayUnsizedOfStorable) {
|
TEST_F(ResolverIsStorableTest, ArrayUnsizedOfStorable) {
|
||||||
auto* arr = create<sem::Array>(create<sem::I32>(), 0, 4, 4, 4, true);
|
auto* arr = create<sem::Array>(create<sem::I32>(), 0, 4, 4, 4, 4);
|
||||||
EXPECT_TRUE(r()->IsStorable(arr));
|
EXPECT_TRUE(r()->IsStorable(arr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -200,36 +200,6 @@ bool Resolver::IsPlain(const sem::Type* type) const {
|
||||||
type->Is<sem::Array>() || type->Is<sem::Struct>();
|
type->Is<sem::Array>() || type->Is<sem::Struct>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types
|
|
||||||
bool Resolver::IsConstructible(const sem::Type* type) const {
|
|
||||||
if (type->Is<sem::Atomic>()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type->is_scalar() || type->Is<sem::Vector>() || type->Is<sem::Matrix>()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto* arr = type->As<sem::Array>()) {
|
|
||||||
if (arr->IsRuntimeSized()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return IsConstructible(arr->ElemType());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto* str = type->As<sem::Struct>()) {
|
|
||||||
for (auto* m : str->Members()) {
|
|
||||||
if (!IsConstructible(m->Type())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://gpuweb.github.io/gpuweb/wgsl.html#storable-types
|
// https://gpuweb.github.io/gpuweb/wgsl.html#storable-types
|
||||||
bool Resolver::IsStorable(const sem::Type* type) const {
|
bool Resolver::IsStorable(const sem::Type* type) const {
|
||||||
return IsPlain(type) || type->Is<sem::Texture>() || type->Is<sem::Sampler>();
|
return IsPlain(type) || type->Is<sem::Texture>() || type->Is<sem::Sampler>();
|
||||||
|
@ -1208,7 +1178,7 @@ bool Resolver::ValidateFunctionParameter(const ast::Function* func,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsPlain(info->type)) {
|
if (IsPlain(info->type)) {
|
||||||
if (!IsConstructible(info->type) &&
|
if (!info->type->IsConstructible() &&
|
||||||
IsValidationEnabled(
|
IsValidationEnabled(
|
||||||
info->declaration->decorations(),
|
info->declaration->decorations(),
|
||||||
ast::DisabledValidation::kIgnoreConstructibleFunctionParameter)) {
|
ast::DisabledValidation::kIgnoreConstructibleFunctionParameter)) {
|
||||||
|
@ -1411,7 +1381,7 @@ bool Resolver::ValidateFunction(const ast::Function* func,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!info->return_type->Is<sem::Void>()) {
|
if (!info->return_type->Is<sem::Void>()) {
|
||||||
if (!IsConstructible(info->return_type)) {
|
if (!info->return_type->IsConstructible()) {
|
||||||
AddError("function return type must be a constructible type",
|
AddError("function return type must be a constructible type",
|
||||||
func->return_type()->source());
|
func->return_type()->source());
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -83,10 +83,6 @@ class Resolver {
|
||||||
/// @returns true if the given type is a plain type
|
/// @returns true if the given type is a plain type
|
||||||
bool IsPlain(const sem::Type* type) const;
|
bool IsPlain(const sem::Type* type) const;
|
||||||
|
|
||||||
/// @param type the given type
|
|
||||||
/// @returns true if the given type is a constructible type
|
|
||||||
bool IsConstructible(const sem::Type* type) const;
|
|
||||||
|
|
||||||
/// @param type the given type
|
/// @param type the given type
|
||||||
/// @returns true if the given type is storable
|
/// @returns true if the given type is storable
|
||||||
bool IsStorable(const sem::Type* type) const;
|
bool IsStorable(const sem::Type* type) const;
|
||||||
|
|
|
@ -34,10 +34,16 @@ Array::Array(const Type* element,
|
||||||
align_(align),
|
align_(align),
|
||||||
size_(size),
|
size_(size),
|
||||||
stride_(stride),
|
stride_(stride),
|
||||||
implicit_stride_(implicit_stride) {
|
implicit_stride_(implicit_stride),
|
||||||
|
constructible_(count > 0 // Runtime-sized arrays are not constructible
|
||||||
|
&& element->IsConstructible()) {
|
||||||
TINT_ASSERT(Semantic, element_);
|
TINT_ASSERT(Semantic, element_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Array::IsConstructible() const {
|
||||||
|
return constructible_;
|
||||||
|
}
|
||||||
|
|
||||||
std::string Array::type_name() const {
|
std::string Array::type_name() const {
|
||||||
std::string type_name = "__array" + element_->type_name();
|
std::string type_name = "__array" + element_->type_name();
|
||||||
type_name += "_count_" + std::to_string(count_);
|
type_name += "_count_" + std::to_string(count_);
|
||||||
|
|
|
@ -85,6 +85,10 @@ class Array : public Castable<Array, Type> {
|
||||||
/// @returns true if this array is runtime sized
|
/// @returns true if this array is runtime sized
|
||||||
bool IsRuntimeSized() const { return count_ == 0; }
|
bool IsRuntimeSized() const { return count_ == 0; }
|
||||||
|
|
||||||
|
/// @returns true if constructible as per
|
||||||
|
/// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types
|
||||||
|
bool IsConstructible() const override;
|
||||||
|
|
||||||
/// @returns the name for the type
|
/// @returns the name for the type
|
||||||
std::string type_name() const override;
|
std::string type_name() const override;
|
||||||
|
|
||||||
|
@ -100,6 +104,7 @@ class Array : public Castable<Array, Type> {
|
||||||
uint32_t const size_;
|
uint32_t const size_;
|
||||||
uint32_t const stride_;
|
uint32_t const stride_;
|
||||||
uint32_t const implicit_stride_;
|
uint32_t const implicit_stride_;
|
||||||
|
bool const constructible_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sem
|
} // namespace sem
|
||||||
|
|
|
@ -35,5 +35,9 @@ std::string Bool::FriendlyName(const SymbolTable&) const {
|
||||||
return "bool";
|
return "bool";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Bool::IsConstructible() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sem
|
} // namespace sem
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -44,6 +44,10 @@ class Bool : public Castable<Bool, Type> {
|
||||||
/// @returns the name for this type that closely resembles how it would be
|
/// @returns the name for this type that closely resembles how it would be
|
||||||
/// declared in WGSL.
|
/// declared in WGSL.
|
||||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||||
|
|
||||||
|
/// @returns true if constructible as per
|
||||||
|
/// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types
|
||||||
|
bool IsConstructible() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sem
|
} // namespace sem
|
||||||
|
|
|
@ -35,5 +35,9 @@ std::string F32::FriendlyName(const SymbolTable&) const {
|
||||||
return "f32";
|
return "f32";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool F32::IsConstructible() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sem
|
} // namespace sem
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -38,6 +38,10 @@ class F32 : public Castable<F32, Type> {
|
||||||
/// @returns the name for this type that closely resembles how it would be
|
/// @returns the name for this type that closely resembles how it would be
|
||||||
/// declared in WGSL.
|
/// declared in WGSL.
|
||||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||||
|
|
||||||
|
/// @returns true if constructible as per
|
||||||
|
/// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types
|
||||||
|
bool IsConstructible() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sem
|
} // namespace sem
|
||||||
|
|
|
@ -35,5 +35,9 @@ std::string I32::FriendlyName(const SymbolTable&) const {
|
||||||
return "i32";
|
return "i32";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool I32::IsConstructible() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sem
|
} // namespace sem
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -38,6 +38,10 @@ class I32 : public Castable<I32, Type> {
|
||||||
/// @returns the name for this type that closely resembles how it would be
|
/// @returns the name for this type that closely resembles how it would be
|
||||||
/// declared in WGSL.
|
/// declared in WGSL.
|
||||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||||
|
|
||||||
|
/// @returns true if constructible as per
|
||||||
|
/// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types
|
||||||
|
bool IsConstructible() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sem
|
} // namespace sem
|
||||||
|
|
|
@ -49,5 +49,9 @@ std::string Matrix::FriendlyName(const SymbolTable& symbols) const {
|
||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Matrix::IsConstructible() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sem
|
} // namespace sem
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -54,6 +54,10 @@ class Matrix : public Castable<Matrix, Type> {
|
||||||
/// declared in WGSL.
|
/// declared in WGSL.
|
||||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||||
|
|
||||||
|
/// @returns true if constructible as per
|
||||||
|
/// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types
|
||||||
|
bool IsConstructible() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type* const subtype_;
|
Type* const subtype_;
|
||||||
Vector* const column_type_;
|
Vector* const column_type_;
|
||||||
|
|
|
@ -35,7 +35,15 @@ Struct::Struct(const ast::Struct* declaration,
|
||||||
members_(std::move(members)),
|
members_(std::move(members)),
|
||||||
align_(align),
|
align_(align),
|
||||||
size_(size),
|
size_(size),
|
||||||
size_no_padding_(size_no_padding) {}
|
size_no_padding_(size_no_padding) {
|
||||||
|
constructible_ = true;
|
||||||
|
for (auto* member : members_) {
|
||||||
|
if (!member->Type()->IsConstructible()) {
|
||||||
|
constructible_ = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Struct::~Struct() = default;
|
Struct::~Struct() = default;
|
||||||
|
|
||||||
|
@ -56,6 +64,10 @@ std::string Struct::FriendlyName(const SymbolTable& symbols) const {
|
||||||
return symbols.NameFor(declaration_->name());
|
return symbols.NameFor(declaration_->name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Struct::IsConstructible() const {
|
||||||
|
return constructible_;
|
||||||
|
}
|
||||||
|
|
||||||
StructMember::StructMember(ast::StructMember* declaration,
|
StructMember::StructMember(ast::StructMember* declaration,
|
||||||
sem::Type* type,
|
sem::Type* type,
|
||||||
uint32_t index,
|
uint32_t index,
|
||||||
|
|
|
@ -148,6 +148,10 @@ class Struct : public Castable<Struct, Type> {
|
||||||
/// declared in WGSL.
|
/// declared in WGSL.
|
||||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||||
|
|
||||||
|
/// @returns true if constructible as per
|
||||||
|
/// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types
|
||||||
|
bool IsConstructible() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint64_t LargestMemberBaseAlignment(MemoryLayout mem_layout) const;
|
uint64_t LargestMemberBaseAlignment(MemoryLayout mem_layout) const;
|
||||||
|
|
||||||
|
@ -158,6 +162,7 @@ class Struct : public Castable<Struct, Type> {
|
||||||
uint32_t const size_no_padding_;
|
uint32_t const size_no_padding_;
|
||||||
std::unordered_set<ast::StorageClass> storage_class_usage_;
|
std::unordered_set<ast::StorageClass> storage_class_usage_;
|
||||||
std::unordered_set<PipelineStageUsage> pipeline_stage_uses_;
|
std::unordered_set<PipelineStageUsage> pipeline_stage_uses_;
|
||||||
|
bool constructible_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// StructMember holds the semantic information for structure members.
|
/// StructMember holds the semantic information for structure members.
|
||||||
|
|
|
@ -111,6 +111,10 @@ void Type::GetDefaultAlignAndSize(uint32_t& align, uint32_t& size) const {
|
||||||
TINT_ASSERT(Semantic, false);
|
TINT_ASSERT(Semantic, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Type::IsConstructible() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool Type::is_scalar() const {
|
bool Type::is_scalar() const {
|
||||||
return IsAnyOf<F32, U32, I32, Bool>();
|
return IsAnyOf<F32, U32, I32, Bool>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,10 @@ class Type : public Castable<Type, Node> {
|
||||||
/// @param size the output default size in bytes for this type.
|
/// @param size the output default size in bytes for this type.
|
||||||
void GetDefaultAlignAndSize(uint32_t& align, uint32_t& size) const;
|
void GetDefaultAlignAndSize(uint32_t& align, uint32_t& size) const;
|
||||||
|
|
||||||
|
/// @returns true if constructible as per
|
||||||
|
/// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types
|
||||||
|
virtual bool IsConstructible() const;
|
||||||
|
|
||||||
/// @returns true if this type is a scalar
|
/// @returns true if this type is a scalar
|
||||||
bool is_scalar() const;
|
bool is_scalar() const;
|
||||||
/// @returns true if this type is a numeric scalar
|
/// @returns true if this type is a numeric scalar
|
||||||
|
|
|
@ -35,5 +35,9 @@ std::string U32::FriendlyName(const SymbolTable&) const {
|
||||||
return "u32";
|
return "u32";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool U32::IsConstructible() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sem
|
} // namespace sem
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -38,6 +38,10 @@ class U32 : public Castable<U32, Type> {
|
||||||
/// @returns the name for this type that closely resembles how it would be
|
/// @returns the name for this type that closely resembles how it would be
|
||||||
/// declared in WGSL.
|
/// declared in WGSL.
|
||||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||||
|
|
||||||
|
/// @returns true if constructible as per
|
||||||
|
/// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types
|
||||||
|
bool IsConstructible() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sem
|
} // namespace sem
|
||||||
|
|
|
@ -41,5 +41,9 @@ std::string Vector::FriendlyName(const SymbolTable& symbols) const {
|
||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Vector::IsConstructible() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sem
|
} // namespace sem
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -46,6 +46,10 @@ class Vector : public Castable<Vector, Type> {
|
||||||
/// declared in WGSL.
|
/// declared in WGSL.
|
||||||
std::string FriendlyName(const SymbolTable& symbols) const override;
|
std::string FriendlyName(const SymbolTable& symbols) const override;
|
||||||
|
|
||||||
|
/// @returns true if constructible as per
|
||||||
|
/// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types
|
||||||
|
bool IsConstructible() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type const* const subtype_;
|
Type const* const subtype_;
|
||||||
uint32_t const size_;
|
uint32_t const size_;
|
||||||
|
|
Loading…
Reference in New Issue