diff --git a/src/intrinsic_table_test.cc b/src/intrinsic_table_test.cc index 5ff0654b05..2635312a4e 100644 --- a/src/intrinsic_table_test.cc +++ b/src/intrinsic_table_test.cc @@ -215,7 +215,7 @@ TEST_F(IntrinsicTableTest, MismatchPointer) { } TEST_F(IntrinsicTableTest, MatchArray) { - auto* arr = create(create(), 0, 4, 4, 4, true); + auto* arr = create(create(), 0, 4, 4, 4, 4); auto* arr_ptr = create(arr, ast::StorageClass::kStorage, ast::Access::kReadWrite); auto* result = diff --git a/src/resolver/inferred_type_test.cc b/src/resolver/inferred_type_test.cc index 789964bc93..5bd957bc22 100644 --- a/src/resolver/inferred_type_test.cc +++ b/src/resolver/inferred_type_test.cc @@ -142,7 +142,7 @@ INSTANTIATE_TEST_SUITE_P(ResolverTest, TEST_F(ResolverInferredTypeTest, InferArray_Pass) { auto* type = ty.array(ty.u32(), 10); auto* expected_type = - create(create(), 10, 4, 4 * 10, 4, true); + create(create(), 10, 4, 4 * 10, 4, 4); auto* ctor_expr = Construct(type); auto* var = Var("a", nullptr, ast::StorageClass::kFunction, ctor_expr); diff --git a/src/resolver/is_host_shareable_test.cc b/src/resolver/is_host_shareable_test.cc index 5da1626578..804d8ee0f5 100644 --- a/src/resolver/is_host_shareable_test.cc +++ b/src/resolver/is_host_shareable_test.cc @@ -99,12 +99,12 @@ TEST_F(ResolverIsHostShareable, Atomic) { } TEST_F(ResolverIsHostShareable, ArraySizedOfHostShareable) { - auto* arr = create(create(), 5, 4, 20, 4, true); + auto* arr = create(create(), 5, 4, 20, 4, 4); EXPECT_TRUE(r()->IsHostShareable(arr)); } TEST_F(ResolverIsHostShareable, ArrayUnsizedOfHostShareable) { - auto* arr = create(create(), 0, 4, 4, 4, true); + auto* arr = create(create(), 0, 4, 4, 4, 4); EXPECT_TRUE(r()->IsHostShareable(arr)); } diff --git a/src/resolver/is_storeable_test.cc b/src/resolver/is_storeable_test.cc index e1495c1221..f084d27a6c 100644 --- a/src/resolver/is_storeable_test.cc +++ b/src/resolver/is_storeable_test.cc @@ -74,12 +74,12 @@ TEST_F(ResolverIsStorableTest, Atomic) { } TEST_F(ResolverIsStorableTest, ArraySizedOfStorable) { - auto* arr = create(create(), 5, 4, 20, 4, true); + auto* arr = create(create(), 5, 4, 20, 4, 4); EXPECT_TRUE(r()->IsStorable(arr)); } TEST_F(ResolverIsStorableTest, ArrayUnsizedOfStorable) { - auto* arr = create(create(), 0, 4, 4, 4, true); + auto* arr = create(create(), 0, 4, 4, 4, 4); EXPECT_TRUE(r()->IsStorable(arr)); } diff --git a/src/resolver/resolver.cc b/src/resolver/resolver.cc index e485c05380..35812c4d09 100644 --- a/src/resolver/resolver.cc +++ b/src/resolver/resolver.cc @@ -200,36 +200,6 @@ bool Resolver::IsPlain(const sem::Type* type) const { type->Is() || type->Is(); } -// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types -bool Resolver::IsConstructible(const sem::Type* type) const { - if (type->Is()) { - return false; - } - - if (type->is_scalar() || type->Is() || type->Is()) { - return true; - } - - if (auto* arr = type->As()) { - if (arr->IsRuntimeSized()) { - return false; - } - - return IsConstructible(arr->ElemType()); - } - - if (auto* str = type->As()) { - for (auto* m : str->Members()) { - if (!IsConstructible(m->Type())) { - return false; - } - } - return true; - } - - return false; -} - // https://gpuweb.github.io/gpuweb/wgsl.html#storable-types bool Resolver::IsStorable(const sem::Type* type) const { return IsPlain(type) || type->Is() || type->Is(); @@ -1208,7 +1178,7 @@ bool Resolver::ValidateFunctionParameter(const ast::Function* func, } if (IsPlain(info->type)) { - if (!IsConstructible(info->type) && + if (!info->type->IsConstructible() && IsValidationEnabled( info->declaration->decorations(), ast::DisabledValidation::kIgnoreConstructibleFunctionParameter)) { @@ -1411,7 +1381,7 @@ bool Resolver::ValidateFunction(const ast::Function* func, } if (!info->return_type->Is()) { - if (!IsConstructible(info->return_type)) { + if (!info->return_type->IsConstructible()) { AddError("function return type must be a constructible type", func->return_type()->source()); return false; diff --git a/src/resolver/resolver.h b/src/resolver/resolver.h index 0cbcc6f39d..6afb4c7109 100644 --- a/src/resolver/resolver.h +++ b/src/resolver/resolver.h @@ -83,10 +83,6 @@ class Resolver { /// @returns true if the given type is a plain type 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 /// @returns true if the given type is storable bool IsStorable(const sem::Type* type) const; diff --git a/src/sem/array.cc b/src/sem/array.cc index 9dd6ea881d..8e3a7349bf 100644 --- a/src/sem/array.cc +++ b/src/sem/array.cc @@ -34,10 +34,16 @@ Array::Array(const Type* element, align_(align), size_(size), 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_); } +bool Array::IsConstructible() const { + return constructible_; +} + std::string Array::type_name() const { std::string type_name = "__array" + element_->type_name(); type_name += "_count_" + std::to_string(count_); diff --git a/src/sem/array.h b/src/sem/array.h index 634dcfdf30..592c538c90 100644 --- a/src/sem/array.h +++ b/src/sem/array.h @@ -85,6 +85,10 @@ class Array : public Castable { /// @returns true if this array is runtime sized 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 std::string type_name() const override; @@ -100,6 +104,7 @@ class Array : public Castable { uint32_t const size_; uint32_t const stride_; uint32_t const implicit_stride_; + bool const constructible_; }; } // namespace sem diff --git a/src/sem/bool_type.cc b/src/sem/bool_type.cc index 817693fc29..aec4f6b80c 100644 --- a/src/sem/bool_type.cc +++ b/src/sem/bool_type.cc @@ -35,5 +35,9 @@ std::string Bool::FriendlyName(const SymbolTable&) const { return "bool"; } +bool Bool::IsConstructible() const { + return true; +} + } // namespace sem } // namespace tint diff --git a/src/sem/bool_type.h b/src/sem/bool_type.h index af2a21cdac..b9fa24dbeb 100644 --- a/src/sem/bool_type.h +++ b/src/sem/bool_type.h @@ -44,6 +44,10 @@ class Bool : public Castable { /// @returns the name for this type that closely resembles how it would be /// declared in WGSL. 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 diff --git a/src/sem/f32_type.cc b/src/sem/f32_type.cc index 12f5c1ef42..49d8666520 100644 --- a/src/sem/f32_type.cc +++ b/src/sem/f32_type.cc @@ -35,5 +35,9 @@ std::string F32::FriendlyName(const SymbolTable&) const { return "f32"; } +bool F32::IsConstructible() const { + return true; +} + } // namespace sem } // namespace tint diff --git a/src/sem/f32_type.h b/src/sem/f32_type.h index 54dc1cd40b..2d359828f3 100644 --- a/src/sem/f32_type.h +++ b/src/sem/f32_type.h @@ -38,6 +38,10 @@ class F32 : public Castable { /// @returns the name for this type that closely resembles how it would be /// declared in WGSL. 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 diff --git a/src/sem/i32_type.cc b/src/sem/i32_type.cc index dcc6a78c49..0b24e8762a 100644 --- a/src/sem/i32_type.cc +++ b/src/sem/i32_type.cc @@ -35,5 +35,9 @@ std::string I32::FriendlyName(const SymbolTable&) const { return "i32"; } +bool I32::IsConstructible() const { + return true; +} + } // namespace sem } // namespace tint diff --git a/src/sem/i32_type.h b/src/sem/i32_type.h index 27bd3bb70d..4621306dc5 100644 --- a/src/sem/i32_type.h +++ b/src/sem/i32_type.h @@ -38,6 +38,10 @@ class I32 : public Castable { /// @returns the name for this type that closely resembles how it would be /// declared in WGSL. 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 diff --git a/src/sem/matrix_type.cc b/src/sem/matrix_type.cc index 2de6a01490..c095f7ce84 100644 --- a/src/sem/matrix_type.cc +++ b/src/sem/matrix_type.cc @@ -49,5 +49,9 @@ std::string Matrix::FriendlyName(const SymbolTable& symbols) const { return out.str(); } +bool Matrix::IsConstructible() const { + return true; +} + } // namespace sem } // namespace tint diff --git a/src/sem/matrix_type.h b/src/sem/matrix_type.h index d91ded059f..d3724fadf9 100644 --- a/src/sem/matrix_type.h +++ b/src/sem/matrix_type.h @@ -54,6 +54,10 @@ class Matrix : public Castable { /// declared in WGSL. 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: Type* const subtype_; Vector* const column_type_; diff --git a/src/sem/struct.cc b/src/sem/struct.cc index 536599771b..317402e97b 100644 --- a/src/sem/struct.cc +++ b/src/sem/struct.cc @@ -35,7 +35,15 @@ Struct::Struct(const ast::Struct* declaration, members_(std::move(members)), align_(align), 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; @@ -56,6 +64,10 @@ std::string Struct::FriendlyName(const SymbolTable& symbols) const { return symbols.NameFor(declaration_->name()); } +bool Struct::IsConstructible() const { + return constructible_; +} + StructMember::StructMember(ast::StructMember* declaration, sem::Type* type, uint32_t index, diff --git a/src/sem/struct.h b/src/sem/struct.h index 6694d6d894..e4595c9c87 100644 --- a/src/sem/struct.h +++ b/src/sem/struct.h @@ -148,6 +148,10 @@ class Struct : public Castable { /// declared in WGSL. 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: uint64_t LargestMemberBaseAlignment(MemoryLayout mem_layout) const; @@ -158,6 +162,7 @@ class Struct : public Castable { uint32_t const size_no_padding_; std::unordered_set storage_class_usage_; std::unordered_set pipeline_stage_uses_; + bool constructible_; }; /// StructMember holds the semantic information for structure members. diff --git a/src/sem/type.cc b/src/sem/type.cc index bddc470023..338d8fde6a 100644 --- a/src/sem/type.cc +++ b/src/sem/type.cc @@ -111,6 +111,10 @@ void Type::GetDefaultAlignAndSize(uint32_t& align, uint32_t& size) const { TINT_ASSERT(Semantic, false); } +bool Type::IsConstructible() const { + return false; +} + bool Type::is_scalar() const { return IsAnyOf(); } diff --git a/src/sem/type.h b/src/sem/type.h index 3a268d4eb7..81a11d9c85 100644 --- a/src/sem/type.h +++ b/src/sem/type.h @@ -56,6 +56,10 @@ class Type : public Castable { /// @param size the output default size in bytes for this type. 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 bool is_scalar() const; /// @returns true if this type is a numeric scalar diff --git a/src/sem/u32_type.cc b/src/sem/u32_type.cc index 8dced5f750..dbc42b020f 100644 --- a/src/sem/u32_type.cc +++ b/src/sem/u32_type.cc @@ -35,5 +35,9 @@ std::string U32::FriendlyName(const SymbolTable&) const { return "u32"; } +bool U32::IsConstructible() const { + return true; +} + } // namespace sem } // namespace tint diff --git a/src/sem/u32_type.h b/src/sem/u32_type.h index b530b79e3c..cf68da683b 100644 --- a/src/sem/u32_type.h +++ b/src/sem/u32_type.h @@ -38,6 +38,10 @@ class U32 : public Castable { /// @returns the name for this type that closely resembles how it would be /// declared in WGSL. 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 diff --git a/src/sem/vector_type.cc b/src/sem/vector_type.cc index 4b6fe20761..74cea14526 100644 --- a/src/sem/vector_type.cc +++ b/src/sem/vector_type.cc @@ -41,5 +41,9 @@ std::string Vector::FriendlyName(const SymbolTable& symbols) const { return out.str(); } +bool Vector::IsConstructible() const { + return true; +} + } // namespace sem } // namespace tint diff --git a/src/sem/vector_type.h b/src/sem/vector_type.h index 5f8d319567..79d8835879 100644 --- a/src/sem/vector_type.h +++ b/src/sem/vector_type.h @@ -46,6 +46,10 @@ class Vector : public Castable { /// declared in WGSL. 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: Type const* const subtype_; uint32_t const size_;