tint/sem: Add Type::Flags()
Use a utils::EnumSet to hold type flags.
This scales better than adding a virtual method for each flag.
Change IsConstructable() from virtual to inline method.
Also remove sem::MemoryLayout. This was some cruft from something
removed a long time ago.
Change-Id: Ib3371946d7f4b07692255641425ccf621dc3e2f4
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/106220
Commit-Queue: Ben Clayton <bclayton@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
diff --git a/src/tint/resolver/intrinsic_table.cc b/src/tint/resolver/intrinsic_table.cc
index 314e619..7b0e3bc 100644
--- a/src/tint/resolver/intrinsic_table.cc
+++ b/src/tint/resolver/intrinsic_table.cc
@@ -58,7 +58,7 @@
/// A special type that matches all TypeMatchers
class Any final : public Castable<Any, sem::Type> {
public:
- Any() = default;
+ Any() : Base(sem::TypeFlags{}) {}
~Any() override = default;
// Stub implementations for sem::Type conformance.
diff --git a/src/tint/sem/abstract_numeric.cc b/src/tint/sem/abstract_numeric.cc
index e7d1846..39615cd 100644
--- a/src/tint/sem/abstract_numeric.cc
+++ b/src/tint/sem/abstract_numeric.cc
@@ -18,7 +18,7 @@
namespace tint::sem {
-AbstractNumeric::AbstractNumeric() = default;
+AbstractNumeric::AbstractNumeric() : Base(TypeFlags{Flag::kConstructable}) {}
AbstractNumeric::AbstractNumeric(AbstractNumeric&&) = default;
AbstractNumeric::~AbstractNumeric() = default;
@@ -30,8 +30,4 @@
return 0;
}
-bool AbstractNumeric::IsConstructible() const {
- return true;
-}
-
} // namespace tint::sem
diff --git a/src/tint/sem/abstract_numeric.h b/src/tint/sem/abstract_numeric.h
index 620c528..68f21ae 100644
--- a/src/tint/sem/abstract_numeric.h
+++ b/src/tint/sem/abstract_numeric.h
@@ -37,9 +37,6 @@
/// @returns 0, as the type is abstract.
uint32_t Align() const override;
-
- /// @returns true.
- bool IsConstructible() const override;
};
} // namespace tint::sem
diff --git a/src/tint/sem/array.cc b/src/tint/sem/array.cc
index 74ef382..ed95e62 100644
--- a/src/tint/sem/array.cc
+++ b/src/tint/sem/array.cc
@@ -26,6 +26,21 @@
namespace tint::sem {
+namespace {
+
+TypeFlags FlagsFrom(const Type* element, ArrayCount count) {
+ TypeFlags flags;
+ // Only constant-expression sized arrays are constructible
+ if (std::holds_alternative<ConstantArrayCount>(count)) {
+ if (element->IsConstructible()) {
+ flags.Add(TypeFlag::kConstructable);
+ }
+ }
+ return flags;
+}
+
+} // namespace
+
const char* const Array::kErrExpectedConstantCount =
"array size is an override-expression, when expected a constant-expression.\n"
"Was the SubstituteOverride transform run?";
@@ -36,15 +51,13 @@
uint32_t size,
uint32_t stride,
uint32_t implicit_stride)
- : element_(element),
+ : Base(FlagsFrom(element, count)),
+ element_(element),
count_(count),
align_(align),
size_(size),
stride_(stride),
- implicit_stride_(implicit_stride),
- // Only constant-expression sized arrays are constructible
- constructible_(std::holds_alternative<ConstantArrayCount>(count) &&
- element->IsConstructible()) {
+ implicit_stride_(implicit_stride) {
TINT_ASSERT(Semantic, element_);
}
@@ -62,10 +75,6 @@
return false;
}
-bool Array::IsConstructible() const {
- return constructible_;
-}
-
std::string Array::FriendlyName(const SymbolTable& symbols) const {
std::ostringstream out;
if (!IsStrideImplicit()) {
diff --git a/src/tint/sem/array.h b/src/tint/sem/array.h
index ca66a16..24b2ee8 100644
--- a/src/tint/sem/array.h
+++ b/src/tint/sem/array.h
@@ -184,10 +184,6 @@
/// @returns true if this array is runtime sized
bool IsRuntimeSized() const { return std::holds_alternative<RuntimeArrayCount>(count_); }
- /// @returns true if constructible as per
- /// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types
- bool IsConstructible() const override;
-
/// @param symbols the program's symbol table
/// @returns the name for this type that closely resembles how it would be
/// declared in WGSL.
@@ -200,7 +196,6 @@
const uint32_t size_;
const uint32_t stride_;
const uint32_t implicit_stride_;
- const bool constructible_;
};
} // namespace tint::sem
diff --git a/src/tint/sem/atomic.cc b/src/tint/sem/atomic.cc
index 52951f3..965ebe2 100644
--- a/src/tint/sem/atomic.cc
+++ b/src/tint/sem/atomic.cc
@@ -22,7 +22,7 @@
namespace tint::sem {
-Atomic::Atomic(const sem::Type* subtype) : subtype_(subtype) {
+Atomic::Atomic(const sem::Type* subtype) : Base(TypeFlags{}), subtype_(subtype) {
TINT_ASSERT(AST, !subtype->Is<Reference>());
}
@@ -51,10 +51,6 @@
return subtype_->Align();
}
-bool Atomic::IsConstructible() const {
- return false;
-}
-
Atomic::Atomic(Atomic&&) = default;
Atomic::~Atomic() = default;
diff --git a/src/tint/sem/atomic.h b/src/tint/sem/atomic.h
index 7f6c814..5b405a1 100644
--- a/src/tint/sem/atomic.h
+++ b/src/tint/sem/atomic.h
@@ -53,10 +53,6 @@
/// @returns the alignment in bytes of the type.
uint32_t Align() const override;
- /// @returns true if constructible as per
- /// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types
- bool IsConstructible() const override;
-
private:
sem::Type const* const subtype_;
};
diff --git a/src/tint/sem/bool.cc b/src/tint/sem/bool.cc
index 938a935..8d3d1bf 100644
--- a/src/tint/sem/bool.cc
+++ b/src/tint/sem/bool.cc
@@ -20,7 +20,7 @@
namespace tint::sem {
-Bool::Bool() = default;
+Bool::Bool() : Base(TypeFlags{Flag::kConstructable}) {}
Bool::Bool(Bool&&) = default;
@@ -38,10 +38,6 @@
return "bool";
}
-bool Bool::IsConstructible() const {
- return true;
-}
-
uint32_t Bool::Size() const {
return 4;
}
diff --git a/src/tint/sem/bool.h b/src/tint/sem/bool.h
index aae48d8..133ab72 100644
--- a/src/tint/sem/bool.h
+++ b/src/tint/sem/bool.h
@@ -48,10 +48,6 @@
/// 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;
-
/// @returns the size in bytes of the type.
/// @note: booleans are not host-sharable, but still may exist in workgroup
/// storage.
diff --git a/src/tint/sem/f16.cc b/src/tint/sem/f16.cc
index 7da65fa..0595821 100644
--- a/src/tint/sem/f16.cc
+++ b/src/tint/sem/f16.cc
@@ -21,7 +21,7 @@
namespace tint {
namespace sem {
-F16::F16() = default;
+F16::F16() : Base(TypeFlags{Flag::kConstructable}) {}
F16::F16(F16&&) = default;
@@ -39,10 +39,6 @@
return "f16";
}
-bool F16::IsConstructible() const {
- return true;
-}
-
uint32_t F16::Size() const {
return 2;
}
diff --git a/src/tint/sem/f16.h b/src/tint/sem/f16.h
index 87543ed..b126614 100644
--- a/src/tint/sem/f16.h
+++ b/src/tint/sem/f16.h
@@ -42,10 +42,6 @@
/// 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;
-
/// @returns the size in bytes of the type.
uint32_t Size() const override;
diff --git a/src/tint/sem/f32.cc b/src/tint/sem/f32.cc
index 83fffcc..c1f99eb 100644
--- a/src/tint/sem/f32.cc
+++ b/src/tint/sem/f32.cc
@@ -20,7 +20,7 @@
namespace tint::sem {
-F32::F32() = default;
+F32::F32() : Base(TypeFlags{Flag::kConstructable}) {}
F32::F32(F32&&) = default;
@@ -38,10 +38,6 @@
return "f32";
}
-bool F32::IsConstructible() const {
- return true;
-}
-
uint32_t F32::Size() const {
return 4;
}
diff --git a/src/tint/sem/f32.h b/src/tint/sem/f32.h
index c7d7ad6..0559dfd 100644
--- a/src/tint/sem/f32.h
+++ b/src/tint/sem/f32.h
@@ -42,10 +42,6 @@
/// 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;
-
/// @returns the size in bytes of the type.
uint32_t Size() const override;
diff --git a/src/tint/sem/i32.cc b/src/tint/sem/i32.cc
index d5a1e26..8047c29 100644
--- a/src/tint/sem/i32.cc
+++ b/src/tint/sem/i32.cc
@@ -20,7 +20,7 @@
namespace tint::sem {
-I32::I32() = default;
+I32::I32() : Base(TypeFlags{Flag::kConstructable}) {}
I32::I32(I32&&) = default;
@@ -38,10 +38,6 @@
return "i32";
}
-bool I32::IsConstructible() const {
- return true;
-}
-
uint32_t I32::Size() const {
return 4;
}
diff --git a/src/tint/sem/i32.h b/src/tint/sem/i32.h
index 3b564db..ff2df4d 100644
--- a/src/tint/sem/i32.h
+++ b/src/tint/sem/i32.h
@@ -42,10 +42,6 @@
/// 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;
-
/// @returns the size in bytes of the type.
uint32_t Size() const override;
diff --git a/src/tint/sem/matrix.cc b/src/tint/sem/matrix.cc
index 7f0383b..5a3eb09 100644
--- a/src/tint/sem/matrix.cc
+++ b/src/tint/sem/matrix.cc
@@ -23,7 +23,8 @@
namespace tint::sem {
Matrix::Matrix(const Vector* column_type, uint32_t columns)
- : subtype_(column_type->type()),
+ : Base(TypeFlags{Flag::kConstructable}),
+ subtype_(column_type->type()),
column_type_(column_type),
rows_(column_type->Width()),
columns_(columns) {
@@ -54,10 +55,6 @@
return out.str();
}
-bool Matrix::IsConstructible() const {
- return true;
-}
-
uint32_t Matrix::Size() const {
return column_type_->Align() * columns();
}
diff --git a/src/tint/sem/matrix.h b/src/tint/sem/matrix.h
index 0321c4b..5d32269 100644
--- a/src/tint/sem/matrix.h
+++ b/src/tint/sem/matrix.h
@@ -59,10 +59,6 @@
/// 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;
-
/// @returns the size in bytes of the type. This may include tail padding.
uint32_t Size() const override;
diff --git a/src/tint/sem/pointer.cc b/src/tint/sem/pointer.cc
index 3918233..b35185a 100644
--- a/src/tint/sem/pointer.cc
+++ b/src/tint/sem/pointer.cc
@@ -23,7 +23,7 @@
namespace tint::sem {
Pointer::Pointer(const Type* subtype, ast::AddressSpace address_space, ast::Access access)
- : subtype_(subtype), address_space_(address_space), access_(access) {
+ : Base(TypeFlags{}), subtype_(subtype), address_space_(address_space), access_(access) {
TINT_ASSERT(Semantic, !subtype->Is<Reference>());
TINT_ASSERT(Semantic, access != ast::Access::kUndefined);
}
diff --git a/src/tint/sem/reference.cc b/src/tint/sem/reference.cc
index a3a9f24..8d3bb6d 100644
--- a/src/tint/sem/reference.cc
+++ b/src/tint/sem/reference.cc
@@ -22,7 +22,7 @@
namespace tint::sem {
Reference::Reference(const Type* subtype, ast::AddressSpace address_space, ast::Access access)
- : subtype_(subtype), address_space_(address_space), access_(access) {
+ : Base(TypeFlags{}), subtype_(subtype), address_space_(address_space), access_(access) {
TINT_ASSERT(Semantic, !subtype->Is<Reference>());
TINT_ASSERT(Semantic, access != ast::Access::kUndefined);
}
diff --git a/src/tint/sem/sampler.cc b/src/tint/sem/sampler.cc
index 20993cc..598c696 100644
--- a/src/tint/sem/sampler.cc
+++ b/src/tint/sem/sampler.cc
@@ -21,7 +21,7 @@
namespace tint::sem {
-Sampler::Sampler(ast::SamplerKind kind) : kind_(kind) {}
+Sampler::Sampler(ast::SamplerKind kind) : Base(TypeFlags{}), kind_(kind) {}
Sampler::Sampler(Sampler&&) = default;
diff --git a/src/tint/sem/struct.cc b/src/tint/sem/struct.cc
index 7d457e8..4a0a3c1 100644
--- a/src/tint/sem/struct.cc
+++ b/src/tint/sem/struct.cc
@@ -27,6 +27,20 @@
TINT_INSTANTIATE_TYPEINFO(tint::sem::StructMember);
namespace tint::sem {
+namespace {
+
+TypeFlags FlagsFrom(const StructMemberList& members) {
+ TypeFlags flags{TypeFlag::kConstructable};
+ for (auto* member : members) {
+ if (!member->Type()->IsConstructible()) {
+ flags.Remove(TypeFlag::kConstructable);
+ break;
+ }
+ }
+ return flags;
+}
+
+} // namespace
Struct::Struct(const ast::Struct* declaration,
Symbol name,
@@ -34,20 +48,13 @@
uint32_t align,
uint32_t size,
uint32_t size_no_padding)
- : declaration_(declaration),
+ : Base(FlagsFrom(members)),
+ declaration_(declaration),
name_(name),
members_(std::move(members)),
align_(align),
size_(size),
- size_no_padding_(size_no_padding) {
- constructible_ = true;
- for (auto* member : members_) {
- if (!member->Type()->IsConstructible()) {
- constructible_ = false;
- break;
- }
- }
-}
+ size_no_padding_(size_no_padding) {}
Struct::~Struct() = default;
@@ -151,10 +158,6 @@
return ss.str();
}
-bool Struct::IsConstructible() const {
- return constructible_;
-}
-
StructMember::StructMember(const ast::StructMember* declaration,
Symbol name,
const sem::Type* type,
diff --git a/src/tint/sem/struct.h b/src/tint/sem/struct.h
index 80ab53b..f35d5f4 100644
--- a/src/tint/sem/struct.h
+++ b/src/tint/sem/struct.h
@@ -152,13 +152,7 @@
/// including size and alignment information.
std::string Layout(const tint::SymbolTable& symbols) const;
- /// @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;
-
ast::Struct const* const declaration_;
const Symbol name_;
const StructMemberList members_;
@@ -167,7 +161,6 @@
const uint32_t size_no_padding_;
std::unordered_set<ast::AddressSpace> address_space_usage_;
std::unordered_set<PipelineStageUsage> pipeline_stage_uses_;
- bool constructible_;
};
/// StructMember holds the semantic information for structure members.
diff --git a/src/tint/sem/texture.cc b/src/tint/sem/texture.cc
index 02fc918..5e5b1e2 100644
--- a/src/tint/sem/texture.cc
+++ b/src/tint/sem/texture.cc
@@ -18,7 +18,7 @@
namespace tint::sem {
-Texture::Texture(ast::TextureDimension dim) : dim_(dim) {}
+Texture::Texture(ast::TextureDimension dim) : Base(TypeFlags{}), dim_(dim) {}
Texture::Texture(Texture&&) = default;
diff --git a/src/tint/sem/type.cc b/src/tint/sem/type.cc
index fed75e6..7191fc6 100644
--- a/src/tint/sem/type.cc
+++ b/src/tint/sem/type.cc
@@ -34,7 +34,7 @@
namespace tint::sem {
-Type::Type() = default;
+Type::Type(TypeFlags flags) : flags_(flags) {}
Type::Type(Type&&) = default;
@@ -64,10 +64,6 @@
return 0;
}
-bool Type::IsConstructible() const {
- return false;
-}
-
bool Type::is_scalar() const {
return IsAnyOf<F16, F32, U32, I32, AbstractNumeric, Bool>();
}
diff --git a/src/tint/sem/type.h b/src/tint/sem/type.h
index ffa3d01..3b68946 100644
--- a/src/tint/sem/type.h
+++ b/src/tint/sem/type.h
@@ -19,6 +19,7 @@
#include <string>
#include "src/tint/sem/node.h"
+#include "src/tint/utils/enum_set.h"
#include "src/tint/utils/vector.h"
// Forward declarations
@@ -29,12 +30,21 @@
namespace tint::sem {
-/// Supported memory layouts for calculating sizes
-enum class MemoryLayout { kUniformBuffer, kStorageBuffer };
+enum TypeFlag {
+ /// Type is constructable.
+ /// @see https://gpuweb.github.io/gpuweb/wgsl/#constructible-types
+ kConstructable,
+};
+
+/// An alias to utils::EnumSet<TypeFlag>
+using TypeFlags = utils::EnumSet<TypeFlag>;
/// Base class for a type in the system
class Type : public Castable<Type, Node> {
public:
+ /// Alias to TypeFlag
+ using Flag = TypeFlag;
+
/// Move constructor
Type(Type&&);
~Type() override;
@@ -66,9 +76,12 @@
/// @note opaque types will return a size of 0.
virtual uint32_t Align() const;
- /// @returns true if constructible as per
+ /// @returns the flags on the type
+ TypeFlags Flags() { return flags_; }
+
+ /// @returns true if type is constructable
/// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types
- virtual bool IsConstructible() const;
+ inline bool IsConstructible() const { return flags_.Contains(Flag::kConstructable); }
/// @returns true if this type is a scalar
bool is_scalar() const;
@@ -166,7 +179,12 @@
static const sem::Type* Common(utils::VectorRef<const Type*> types);
protected:
- Type();
+ /// Constructor
+ /// @param flags the flags of this type
+ explicit Type(TypeFlags flags);
+
+ /// The flags of this type.
+ const TypeFlags flags_;
};
} // namespace tint::sem
diff --git a/src/tint/sem/u32.cc b/src/tint/sem/u32.cc
index dc3bd1d..91fd7d7 100644
--- a/src/tint/sem/u32.cc
+++ b/src/tint/sem/u32.cc
@@ -20,7 +20,7 @@
namespace tint::sem {
-U32::U32() = default;
+U32::U32() : Base(TypeFlags{Flag::kConstructable}) {}
U32::~U32() = default;
@@ -38,10 +38,6 @@
return "u32";
}
-bool U32::IsConstructible() const {
- return true;
-}
-
uint32_t U32::Size() const {
return 4;
}
diff --git a/src/tint/sem/u32.h b/src/tint/sem/u32.h
index 5ae01fb..b0143d9 100644
--- a/src/tint/sem/u32.h
+++ b/src/tint/sem/u32.h
@@ -42,10 +42,6 @@
/// 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;
-
/// @returns the size in bytes of the type.
uint32_t Size() const override;
diff --git a/src/tint/sem/vector.cc b/src/tint/sem/vector.cc
index 2df7cf0..e6d3acf 100644
--- a/src/tint/sem/vector.cc
+++ b/src/tint/sem/vector.cc
@@ -21,7 +21,8 @@
namespace tint::sem {
-Vector::Vector(Type const* subtype, uint32_t width) : subtype_(subtype), width_(width) {
+Vector::Vector(Type const* subtype, uint32_t width)
+ : Base(TypeFlags{Flag::kConstructable}), subtype_(subtype), width_(width) {
TINT_ASSERT(Semantic, width_ > 1);
TINT_ASSERT(Semantic, width_ < 5);
}
@@ -47,10 +48,6 @@
return out.str();
}
-bool Vector::IsConstructible() const {
- return true;
-}
-
uint32_t Vector::Size() const {
return subtype_->Size() * width_;
}
diff --git a/src/tint/sem/vector.h b/src/tint/sem/vector.h
index 8d9e7a3..163c70d 100644
--- a/src/tint/sem/vector.h
+++ b/src/tint/sem/vector.h
@@ -47,10 +47,6 @@
/// 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;
-
/// @returns the number of elements in the vector
uint32_t Width() const { return width_; }
diff --git a/src/tint/sem/void.cc b/src/tint/sem/void.cc
index b20b96e..8e5e3fb 100644
--- a/src/tint/sem/void.cc
+++ b/src/tint/sem/void.cc
@@ -20,7 +20,7 @@
namespace tint::sem {
-Void::Void() = default;
+Void::Void() : Base(TypeFlags{}) {}
Void::Void(Void&&) = default;