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
class Any final : public Castable<Any, sem::Type> {
public:
Any() = default;
Any() : Base(sem::TypeFlags{}) {}
~Any() override = default;
// Stub implementations for sem::Type conformance.

View File

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

View File

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

View File

@ -26,6 +26,21 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::Array);
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 @@ Array::Array(const Type* element,
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 @@ bool Array::Equals(const sem::Type& other) const {
return false;
}
bool Array::IsConstructible() const {
return constructible_;
}
std::string Array::FriendlyName(const SymbolTable& symbols) const {
std::ostringstream out;
if (!IsStrideImplicit()) {

View File

@ -184,10 +184,6 @@ class Array final : public Castable<Array, Type> {
/// @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 @@ class Array final : public Castable<Array, Type> {
const uint32_t size_;
const uint32_t stride_;
const uint32_t implicit_stride_;
const bool constructible_;
};
} // namespace tint::sem

View File

@ -22,7 +22,7 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::Atomic);
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 @@ uint32_t Atomic::Align() const {
return subtype_->Align();
}
bool Atomic::IsConstructible() const {
return false;
}
Atomic::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.
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_;
};

View File

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

View File

@ -48,10 +48,6 @@ class Bool final : public Castable<Bool, Type> {
/// 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.

View File

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

View File

@ -42,10 +42,6 @@ class F16 final : public Castable<F16, Type> {
/// 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;

View File

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

View File

@ -42,10 +42,6 @@ class F32 final : public Castable<F32, Type> {
/// 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;

View File

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

View File

@ -42,10 +42,6 @@ class I32 final : public Castable<I32, Type> {
/// 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;

View File

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

View File

@ -59,10 +59,6 @@ class Matrix final : public Castable<Matrix, Type> {
/// 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;

View File

@ -23,7 +23,7 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::Pointer);
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);
}

View File

@ -22,7 +22,7 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::Reference);
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);
}

View File

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

View File

@ -27,6 +27,20 @@ TINT_INSTANTIATE_TYPEINFO(tint::sem::Struct);
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 @@ Struct::Struct(const ast::Struct* declaration,
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 @@ std::string Struct::Layout(const tint::SymbolTable& symbols) const {
return ss.str();
}
bool Struct::IsConstructible() const {
return constructible_;
}
StructMember::StructMember(const ast::StructMember* declaration,
Symbol name,
const sem::Type* type,

View File

@ -152,13 +152,7 @@ class Struct final : public Castable<Struct, Type> {
/// 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 @@ class Struct final : public Castable<Struct, Type> {
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.

View File

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

View File

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

View File

@ -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 @@ class SymbolTable;
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 @@ class Type : public Castable<Type, Node> {
/// @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 @@ class Type : public Castable<Type, Node> {
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

View File

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

View File

@ -42,10 +42,6 @@ class U32 final : public Castable<U32, Type> {
/// 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;

View File

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

View File

@ -47,10 +47,6 @@ class Vector final : public Castable<Vector, Type> {
/// 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_; }

View File

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