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>
This commit is contained in:
Ben Clayton 2022-10-25 10:05:18 +00:00 committed by Dawn LUCI CQ
parent 434edc2a12
commit 80b2312493
30 changed files with 76 additions and 131 deletions

View File

@ -58,7 +58,7 @@ constexpr static const size_t kNumFixedCandidates = 8;
/// A special type that matches all TypeMatchers /// A special type that matches all TypeMatchers
class Any final : public Castable<Any, sem::Type> { class Any final : public Castable<Any, sem::Type> {
public: public:
Any() = default; Any() : Base(sem::TypeFlags{}) {}
~Any() override = default; ~Any() override = default;
// Stub implementations for sem::Type conformance. // Stub implementations for sem::Type conformance.

View File

@ -18,7 +18,7 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::AbstractNumeric);
namespace tint::sem { namespace tint::sem {
AbstractNumeric::AbstractNumeric() = default; AbstractNumeric::AbstractNumeric() : Base(TypeFlags{Flag::kConstructable}) {}
AbstractNumeric::AbstractNumeric(AbstractNumeric&&) = default; AbstractNumeric::AbstractNumeric(AbstractNumeric&&) = default;
AbstractNumeric::~AbstractNumeric() = default; AbstractNumeric::~AbstractNumeric() = default;
@ -30,8 +30,4 @@ uint32_t AbstractNumeric::Align() const {
return 0; return 0;
} }
bool AbstractNumeric::IsConstructible() const {
return true;
}
} // namespace tint::sem } // namespace tint::sem

View File

@ -37,9 +37,6 @@ class AbstractNumeric : public Castable<AbstractNumeric, Type> {
/// @returns 0, as the type is abstract. /// @returns 0, as the type is abstract.
uint32_t Align() const override; uint32_t Align() const override;
/// @returns true.
bool IsConstructible() const override;
}; };
} // namespace tint::sem } // namespace tint::sem

View File

@ -26,6 +26,21 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::Array);
namespace tint::sem { 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 = const char* const Array::kErrExpectedConstantCount =
"array size is an override-expression, when expected a constant-expression.\n" "array size is an override-expression, when expected a constant-expression.\n"
"Was the SubstituteOverride transform run?"; "Was the SubstituteOverride transform run?";
@ -36,15 +51,13 @@ Array::Array(const Type* element,
uint32_t size, uint32_t size,
uint32_t stride, uint32_t stride,
uint32_t implicit_stride) uint32_t implicit_stride)
: element_(element), : Base(FlagsFrom(element, count)),
element_(element),
count_(count), count_(count),
align_(align), align_(align),
size_(size), size_(size),
stride_(stride), stride_(stride),
implicit_stride_(implicit_stride), implicit_stride_(implicit_stride) {
// Only constant-expression sized arrays are constructible
constructible_(std::holds_alternative<ConstantArrayCount>(count) &&
element->IsConstructible()) {
TINT_ASSERT(Semantic, element_); TINT_ASSERT(Semantic, element_);
} }
@ -62,10 +75,6 @@ bool Array::Equals(const sem::Type& other) const {
return false; return false;
} }
bool Array::IsConstructible() const {
return constructible_;
}
std::string Array::FriendlyName(const SymbolTable& symbols) const { std::string Array::FriendlyName(const SymbolTable& symbols) const {
std::ostringstream out; std::ostringstream out;
if (!IsStrideImplicit()) { if (!IsStrideImplicit()) {

View File

@ -184,10 +184,6 @@ class Array final : public Castable<Array, Type> {
/// @returns true if this array is runtime sized /// @returns true if this array is runtime sized
bool IsRuntimeSized() const { return std::holds_alternative<RuntimeArrayCount>(count_); } 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 /// @param symbols the program's symbol table
/// @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.
@ -200,7 +196,6 @@ class Array final : public Castable<Array, Type> {
const uint32_t size_; const uint32_t size_;
const uint32_t stride_; const uint32_t stride_;
const uint32_t implicit_stride_; const uint32_t implicit_stride_;
const bool constructible_;
}; };
} // namespace tint::sem } // namespace tint::sem

View File

@ -22,7 +22,7 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::Atomic);
namespace tint::sem { 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>()); TINT_ASSERT(AST, !subtype->Is<Reference>());
} }
@ -51,10 +51,6 @@ uint32_t Atomic::Align() const {
return subtype_->Align(); return subtype_->Align();
} }
bool Atomic::IsConstructible() const {
return false;
}
Atomic::Atomic(Atomic&&) = default; Atomic::Atomic(Atomic&&) = default;
Atomic::~Atomic() = default; Atomic::~Atomic() = default;

View File

@ -53,10 +53,6 @@ class Atomic final : public Castable<Atomic, Type> {
/// @returns the alignment in bytes of the type. /// @returns the alignment in bytes of the type.
uint32_t Align() const override; uint32_t Align() const override;
/// @returns true if constructible as per
/// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types
bool IsConstructible() const override;
private: private:
sem::Type const* const subtype_; sem::Type const* const subtype_;
}; };

View File

@ -20,7 +20,7 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::Bool);
namespace tint::sem { namespace tint::sem {
Bool::Bool() = default; Bool::Bool() : Base(TypeFlags{Flag::kConstructable}) {}
Bool::Bool(Bool&&) = default; Bool::Bool(Bool&&) = default;
@ -38,10 +38,6 @@ std::string Bool::FriendlyName(const SymbolTable&) const {
return "bool"; return "bool";
} }
bool Bool::IsConstructible() const {
return true;
}
uint32_t Bool::Size() const { uint32_t Bool::Size() const {
return 4; return 4;
} }

View File

@ -48,10 +48,6 @@ class Bool final : public Castable<Bool, 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;
/// @returns the size in bytes of the type. /// @returns the size in bytes of the type.
/// @note: booleans are not host-sharable, but still may exist in workgroup /// @note: booleans are not host-sharable, but still may exist in workgroup
/// storage. /// storage.

View File

@ -21,7 +21,7 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::F16);
namespace tint { namespace tint {
namespace sem { namespace sem {
F16::F16() = default; F16::F16() : Base(TypeFlags{Flag::kConstructable}) {}
F16::F16(F16&&) = default; F16::F16(F16&&) = default;
@ -39,10 +39,6 @@ std::string F16::FriendlyName(const SymbolTable&) const {
return "f16"; return "f16";
} }
bool F16::IsConstructible() const {
return true;
}
uint32_t F16::Size() const { uint32_t F16::Size() const {
return 2; return 2;
} }

View File

@ -42,10 +42,6 @@ class F16 final : public Castable<F16, 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;
/// @returns the size in bytes of the type. /// @returns the size in bytes of the type.
uint32_t Size() const override; uint32_t Size() const override;

View File

@ -20,7 +20,7 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::F32);
namespace tint::sem { namespace tint::sem {
F32::F32() = default; F32::F32() : Base(TypeFlags{Flag::kConstructable}) {}
F32::F32(F32&&) = default; F32::F32(F32&&) = default;
@ -38,10 +38,6 @@ std::string F32::FriendlyName(const SymbolTable&) const {
return "f32"; return "f32";
} }
bool F32::IsConstructible() const {
return true;
}
uint32_t F32::Size() const { uint32_t F32::Size() const {
return 4; return 4;
} }

View File

@ -42,10 +42,6 @@ class F32 final : public Castable<F32, 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;
/// @returns the size in bytes of the type. /// @returns the size in bytes of the type.
uint32_t Size() const override; uint32_t Size() const override;

View File

@ -20,7 +20,7 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::I32);
namespace tint::sem { namespace tint::sem {
I32::I32() = default; I32::I32() : Base(TypeFlags{Flag::kConstructable}) {}
I32::I32(I32&&) = default; I32::I32(I32&&) = default;
@ -38,10 +38,6 @@ std::string I32::FriendlyName(const SymbolTable&) const {
return "i32"; return "i32";
} }
bool I32::IsConstructible() const {
return true;
}
uint32_t I32::Size() const { uint32_t I32::Size() const {
return 4; return 4;
} }

View File

@ -42,10 +42,6 @@ class I32 final : public Castable<I32, 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;
/// @returns the size in bytes of the type. /// @returns the size in bytes of the type.
uint32_t Size() const override; uint32_t Size() const override;

View File

@ -23,7 +23,8 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::Matrix);
namespace tint::sem { namespace tint::sem {
Matrix::Matrix(const Vector* column_type, uint32_t columns) 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), column_type_(column_type),
rows_(column_type->Width()), rows_(column_type->Width()),
columns_(columns) { columns_(columns) {
@ -54,10 +55,6 @@ std::string Matrix::FriendlyName(const SymbolTable& symbols) const {
return out.str(); return out.str();
} }
bool Matrix::IsConstructible() const {
return true;
}
uint32_t Matrix::Size() const { uint32_t Matrix::Size() const {
return column_type_->Align() * columns(); return column_type_->Align() * columns();
} }

View File

@ -59,10 +59,6 @@ class Matrix final : 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;
/// @returns the size in bytes of the type. This may include tail padding. /// @returns the size in bytes of the type. This may include tail padding.
uint32_t Size() const override; uint32_t Size() const override;

View File

@ -23,7 +23,7 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::Pointer);
namespace tint::sem { namespace tint::sem {
Pointer::Pointer(const Type* subtype, ast::AddressSpace address_space, ast::Access access) 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, !subtype->Is<Reference>());
TINT_ASSERT(Semantic, access != ast::Access::kUndefined); TINT_ASSERT(Semantic, access != ast::Access::kUndefined);
} }

View File

@ -22,7 +22,7 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::Reference);
namespace tint::sem { namespace tint::sem {
Reference::Reference(const Type* subtype, ast::AddressSpace address_space, ast::Access access) 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, !subtype->Is<Reference>());
TINT_ASSERT(Semantic, access != ast::Access::kUndefined); TINT_ASSERT(Semantic, access != ast::Access::kUndefined);
} }

View File

@ -21,7 +21,7 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::Sampler);
namespace tint::sem { namespace tint::sem {
Sampler::Sampler(ast::SamplerKind kind) : kind_(kind) {} Sampler::Sampler(ast::SamplerKind kind) : Base(TypeFlags{}), kind_(kind) {}
Sampler::Sampler(Sampler&&) = default; Sampler::Sampler(Sampler&&) = default;

View File

@ -27,6 +27,20 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::Struct);
TINT_INSTANTIATE_TYPEINFO(tint::sem::StructMember); TINT_INSTANTIATE_TYPEINFO(tint::sem::StructMember);
namespace tint::sem { 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, Struct::Struct(const ast::Struct* declaration,
Symbol name, Symbol name,
@ -34,20 +48,13 @@ Struct::Struct(const ast::Struct* declaration,
uint32_t align, uint32_t align,
uint32_t size, uint32_t size,
uint32_t size_no_padding) uint32_t size_no_padding)
: declaration_(declaration), : Base(FlagsFrom(members)),
declaration_(declaration),
name_(name), name_(name),
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;
@ -151,10 +158,6 @@ std::string Struct::Layout(const tint::SymbolTable& symbols) const {
return ss.str(); return ss.str();
} }
bool Struct::IsConstructible() const {
return constructible_;
}
StructMember::StructMember(const ast::StructMember* declaration, StructMember::StructMember(const ast::StructMember* declaration,
Symbol name, Symbol name,
const sem::Type* type, const sem::Type* type,

View File

@ -152,13 +152,7 @@ class Struct final : public Castable<Struct, Type> {
/// including size and alignment information. /// including size and alignment information.
std::string Layout(const tint::SymbolTable& symbols) const; 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: private:
uint64_t LargestMemberBaseAlignment(MemoryLayout mem_layout) const;
ast::Struct const* const declaration_; ast::Struct const* const declaration_;
const Symbol name_; const Symbol name_;
const StructMemberList members_; const StructMemberList members_;
@ -167,7 +161,6 @@ class Struct final : public Castable<Struct, Type> {
const uint32_t size_no_padding_; const uint32_t size_no_padding_;
std::unordered_set<ast::AddressSpace> address_space_usage_; std::unordered_set<ast::AddressSpace> address_space_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.

View File

@ -18,7 +18,7 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::Texture);
namespace tint::sem { namespace tint::sem {
Texture::Texture(ast::TextureDimension dim) : dim_(dim) {} Texture::Texture(ast::TextureDimension dim) : Base(TypeFlags{}), dim_(dim) {}
Texture::Texture(Texture&&) = default; Texture::Texture(Texture&&) = default;

View File

@ -34,7 +34,7 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::Type);
namespace tint::sem { namespace tint::sem {
Type::Type() = default; Type::Type(TypeFlags flags) : flags_(flags) {}
Type::Type(Type&&) = default; Type::Type(Type&&) = default;
@ -64,10 +64,6 @@ uint32_t Type::Align() const {
return 0; return 0;
} }
bool Type::IsConstructible() const {
return false;
}
bool Type::is_scalar() const { bool Type::is_scalar() const {
return IsAnyOf<F16, F32, U32, I32, AbstractNumeric, Bool>(); return IsAnyOf<F16, F32, U32, I32, AbstractNumeric, Bool>();
} }

View File

@ -19,6 +19,7 @@
#include <string> #include <string>
#include "src/tint/sem/node.h" #include "src/tint/sem/node.h"
#include "src/tint/utils/enum_set.h"
#include "src/tint/utils/vector.h" #include "src/tint/utils/vector.h"
// Forward declarations // Forward declarations
@ -29,12 +30,21 @@ class SymbolTable;
namespace tint::sem { namespace tint::sem {
/// Supported memory layouts for calculating sizes enum TypeFlag {
enum class MemoryLayout { kUniformBuffer, kStorageBuffer }; /// 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 /// Base class for a type in the system
class Type : public Castable<Type, Node> { class Type : public Castable<Type, Node> {
public: public:
/// Alias to TypeFlag
using Flag = TypeFlag;
/// Move constructor /// Move constructor
Type(Type&&); Type(Type&&);
~Type() override; ~Type() override;
@ -66,9 +76,12 @@ class Type : public Castable<Type, Node> {
/// @note opaque types will return a size of 0. /// @note opaque types will return a size of 0.
virtual uint32_t Align() const; 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 /// 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 /// @returns true if this type is a scalar
bool is_scalar() const; bool is_scalar() const;
@ -166,7 +179,12 @@ class Type : public Castable<Type, Node> {
static const sem::Type* Common(utils::VectorRef<const Type*> types); static const sem::Type* Common(utils::VectorRef<const Type*> types);
protected: 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 } // namespace tint::sem

View File

@ -20,7 +20,7 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::U32);
namespace tint::sem { namespace tint::sem {
U32::U32() = default; U32::U32() : Base(TypeFlags{Flag::kConstructable}) {}
U32::~U32() = default; U32::~U32() = default;
@ -38,10 +38,6 @@ std::string U32::FriendlyName(const SymbolTable&) const {
return "u32"; return "u32";
} }
bool U32::IsConstructible() const {
return true;
}
uint32_t U32::Size() const { uint32_t U32::Size() const {
return 4; return 4;
} }

View File

@ -42,10 +42,6 @@ class U32 final : public Castable<U32, 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;
/// @returns the size in bytes of the type. /// @returns the size in bytes of the type.
uint32_t Size() const override; uint32_t Size() const override;

View File

@ -21,7 +21,8 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::Vector);
namespace tint::sem { 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_ > 1);
TINT_ASSERT(Semantic, width_ < 5); TINT_ASSERT(Semantic, width_ < 5);
} }
@ -47,10 +48,6 @@ std::string Vector::FriendlyName(const SymbolTable& symbols) const {
return out.str(); return out.str();
} }
bool Vector::IsConstructible() const {
return true;
}
uint32_t Vector::Size() const { uint32_t Vector::Size() const {
return subtype_->Size() * width_; return subtype_->Size() * width_;
} }

View File

@ -47,10 +47,6 @@ class Vector final : 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;
/// @returns the number of elements in the vector /// @returns the number of elements in the vector
uint32_t Width() const { return width_; } uint32_t Width() const { return width_; }

View File

@ -20,7 +20,7 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::Void);
namespace tint::sem { namespace tint::sem {
Void::Void() = default; Void::Void() : Base(TypeFlags{}) {}
Void::Void(Void&&) = default; Void::Void(Void&&) = default;