tint: Rework tint::Manager
Don't use dynamic casting in hashing and equality. These should be fast, and dynamic casting is expensive. Add type::UniqueNode for things that need de-duplicating and bin the types on construction. Replace some use of SFINAE with constexpr. Also fixes a build failure for x86. Bug: oss-fuzz:54184 Change-Id: Ic1b0708394f9f5703fc179a2c31ce18bd07e196c Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/114760 Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Antonio Maiorano <amaiorano@google.com> Auto-Submit: Ben Clayton <bclayton@google.com> Reviewed-by: Antonio Maiorano <amaiorano@google.com>
This commit is contained in:
parent
1438e82354
commit
7c3e9a6dd2
|
@ -583,6 +583,7 @@ libtint_source_set("libtint_core_all_src") {
|
|||
"type/texture.h",
|
||||
"type/type.h",
|
||||
"type/u32.h",
|
||||
"type/unique_node.h",
|
||||
"type/vector.h",
|
||||
"type/void.h",
|
||||
"utils/bitcast.h",
|
||||
|
@ -754,6 +755,8 @@ libtint_source_set("libtint_type_src") {
|
|||
"type/type.h",
|
||||
"type/u32.cc",
|
||||
"type/u32.h",
|
||||
"type/unique_node.cc",
|
||||
"type/unique_node.h",
|
||||
"type/vector.cc",
|
||||
"type/vector.h",
|
||||
"type/void.cc",
|
||||
|
|
|
@ -514,6 +514,8 @@ list(APPEND TINT_LIB_SRCS
|
|||
type/type.h
|
||||
type/u32.cc
|
||||
type/u32.h
|
||||
type/unique_node.cc
|
||||
type/unique_node.h
|
||||
type/vector.cc
|
||||
type/vector.h
|
||||
type/void.cc
|
||||
|
|
|
@ -539,35 +539,18 @@ class ProgramBuilder {
|
|||
return constant_nodes_.Create<constant::Splat>(type, element, n);
|
||||
}
|
||||
|
||||
/// Creates a new type::Type owned by the ProgramBuilder.
|
||||
/// When the ProgramBuilder is destructed, owned ProgramBuilder and the
|
||||
/// returned `Type` will also be destructed.
|
||||
/// Types are unique (de-aliased), and so calling create() for the same `T`
|
||||
/// and arguments will return the same pointer.
|
||||
/// @param args the arguments to pass to the type constructor
|
||||
/// @returns the de-aliased type pointer
|
||||
/// Creates a new type::Node owned by the ProgramBuilder.
|
||||
/// When the ProgramBuilder is destructed, owned ProgramBuilder and the returned node will also
|
||||
/// be destructed. If T derives from type::UniqueNode, then the calling create() for the same
|
||||
/// `T` and arguments will return the same pointer.
|
||||
/// @param args the arguments to pass to the constructor
|
||||
/// @returns the new, or existing node
|
||||
template <typename T, typename... ARGS>
|
||||
traits::EnableIfIsType<T, type::Type>* create(ARGS&&... args) {
|
||||
traits::EnableIfIsType<T, type::Node>* create(ARGS&&... args) {
|
||||
AssertNotMoved();
|
||||
return types_.Get<T>(std::forward<ARGS>(args)...);
|
||||
}
|
||||
|
||||
/// Creates a new type::ArrayCount owned by the ProgramBuilder.
|
||||
/// When the ProgramBuilder is destructed, owned ProgramBuilder and the
|
||||
/// returned `ArrayCount` will also be destructed.
|
||||
/// ArrayCounts are unique (de-aliased), and so calling create() for the same `T`
|
||||
/// and arguments will return the same pointer.
|
||||
/// @param args the arguments to pass to the array count constructor
|
||||
/// @returns the de-aliased array count pointer
|
||||
template <typename T, typename... ARGS>
|
||||
traits::EnableIf<traits::IsTypeOrDerived<T, type::ArrayCount> ||
|
||||
traits::IsTypeOrDerived<T, type::StructMember>,
|
||||
T>*
|
||||
create(ARGS&&... args) {
|
||||
AssertNotMoved();
|
||||
return types_.GetNode<T>(std::forward<ARGS>(args)...);
|
||||
}
|
||||
|
||||
/// Marks this builder as moved, preventing any further use of the builder.
|
||||
void MarkAsMoved();
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ class Any final : public Castable<Any, type::Type> {
|
|||
|
||||
// Stub implementations for type::Type conformance.
|
||||
size_t Hash() const override { return 0; }
|
||||
bool Equals(const type::Type&) const override { return false; }
|
||||
bool Equals(const type::UniqueNode&) const override { return false; }
|
||||
std::string FriendlyName(const SymbolTable&) const override { return "<any>"; }
|
||||
};
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ size_t NamedOverrideArrayCount::Hash() const {
|
|||
return static_cast<size_t>(TypeInfo::Of<NamedOverrideArrayCount>().full_hashcode);
|
||||
}
|
||||
|
||||
bool NamedOverrideArrayCount::Equals(const ArrayCount& other) const {
|
||||
bool NamedOverrideArrayCount::Equals(const UniqueNode& other) const {
|
||||
if (auto* v = other.As<NamedOverrideArrayCount>()) {
|
||||
return variable == v->variable;
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ size_t UnnamedOverrideArrayCount::Hash() const {
|
|||
return static_cast<size_t>(TypeInfo::Of<UnnamedOverrideArrayCount>().full_hashcode);
|
||||
}
|
||||
|
||||
bool UnnamedOverrideArrayCount::Equals(const ArrayCount& other) const {
|
||||
bool UnnamedOverrideArrayCount::Equals(const UniqueNode& other) const {
|
||||
if (auto* v = other.As<UnnamedOverrideArrayCount>()) {
|
||||
return expr == v->expr;
|
||||
}
|
||||
|
|
|
@ -39,9 +39,9 @@ class NamedOverrideArrayCount final : public Castable<NamedOverrideArrayCount, t
|
|||
/// @returns a hash of the array count.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param t other array count
|
||||
/// @returns true if this array count is equal to the given array count
|
||||
bool Equals(const type::ArrayCount& t) const override;
|
||||
/// @param other the other node
|
||||
/// @returns true if this array count is equal @p other
|
||||
bool Equals(const type::UniqueNode& other) const override;
|
||||
|
||||
/// @param symbols the symbol table
|
||||
/// @returns the friendly name for this array count
|
||||
|
@ -68,9 +68,9 @@ class UnnamedOverrideArrayCount final
|
|||
/// @returns a hash of the array count.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param t other array count
|
||||
/// @returns true if this array count is equal to the given array count
|
||||
bool Equals(const type::ArrayCount& t) const override;
|
||||
/// @param other the other node
|
||||
/// @returns true if this array count is equal @p other
|
||||
bool Equals(const type::UniqueNode& other) const override;
|
||||
|
||||
/// @param symbols the symbol table
|
||||
/// @returns the friendly name for this array count
|
||||
|
|
|
@ -29,7 +29,7 @@ size_t AbstractFloat::Hash() const {
|
|||
return utils::Hash(TypeInfo::Of<AbstractFloat>().full_hashcode);
|
||||
}
|
||||
|
||||
bool AbstractFloat::Equals(const Type& other) const {
|
||||
bool AbstractFloat::Equals(const UniqueNode& other) const {
|
||||
return other.Is<AbstractFloat>();
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ class AbstractFloat final : public Castable<AbstractFloat, AbstractNumeric> {
|
|||
|
||||
/// @param other the other type to compare against
|
||||
/// @returns true if this type is equal to the given type
|
||||
bool Equals(const Type& other) const override;
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type when printed in diagnostics.
|
||||
|
|
|
@ -29,7 +29,7 @@ size_t AbstractInt::Hash() const {
|
|||
return utils::Hash(TypeInfo::Of<AbstractInt>().full_hashcode);
|
||||
}
|
||||
|
||||
bool AbstractInt::Equals(const Type& other) const {
|
||||
bool AbstractInt::Equals(const UniqueNode& other) const {
|
||||
return other.Is<AbstractInt>();
|
||||
}
|
||||
|
||||
|
|
|
@ -35,9 +35,9 @@ class AbstractInt final : public Castable<AbstractInt, AbstractNumeric> {
|
|||
/// @returns a hash of the type.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param other the other type to compare against
|
||||
/// @returns true if the this type is equal to the given type
|
||||
bool Equals(const Type& other) const override;
|
||||
/// @param other the other node to compare against
|
||||
/// @returns true if the this type is equal to @p other
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type when printed in diagnostics.
|
||||
|
|
|
@ -72,7 +72,7 @@ size_t Array::Hash() const {
|
|||
return utils::Hash(TypeInfo::Of<Array>().full_hashcode, count_, align_, size_, stride_);
|
||||
}
|
||||
|
||||
bool Array::Equals(const Type& other) const {
|
||||
bool Array::Equals(const UniqueNode& other) const {
|
||||
if (auto* o = other.As<Array>()) {
|
||||
// Note: implicit_stride is not part of the type_name string as this is
|
||||
// derived from the element type
|
||||
|
|
|
@ -55,9 +55,9 @@ class Array final : public Castable<Array, Type> {
|
|||
/// @returns a hash of the type.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param other the other type to compare against
|
||||
/// @returns true if the this type is equal to the given type
|
||||
bool Equals(const Type& other) const override;
|
||||
/// @param other the other node to compare against
|
||||
/// @returns true if the this type is equal to @p other
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @return the array element type
|
||||
Type const* ElemType() const { return element_; }
|
||||
|
|
|
@ -30,7 +30,7 @@ size_t ConstantArrayCount::Hash() const {
|
|||
return static_cast<size_t>(TypeInfo::Of<ConstantArrayCount>().full_hashcode);
|
||||
}
|
||||
|
||||
bool ConstantArrayCount::Equals(const ArrayCount& other) const {
|
||||
bool ConstantArrayCount::Equals(const UniqueNode& other) const {
|
||||
if (auto* v = other.As<ConstantArrayCount>()) {
|
||||
return value == v->value;
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ size_t RuntimeArrayCount::Hash() const {
|
|||
return static_cast<size_t>(TypeInfo::Of<RuntimeArrayCount>().full_hashcode);
|
||||
}
|
||||
|
||||
bool RuntimeArrayCount::Equals(const ArrayCount& other) const {
|
||||
bool RuntimeArrayCount::Equals(const UniqueNode& other) const {
|
||||
return other.Is<RuntimeArrayCount>();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,22 +19,15 @@
|
|||
#include <string>
|
||||
|
||||
#include "src/tint/symbol_table.h"
|
||||
#include "src/tint/type/node.h"
|
||||
#include "src/tint/type/unique_node.h"
|
||||
|
||||
namespace tint::type {
|
||||
|
||||
/// An array count
|
||||
class ArrayCount : public Castable<ArrayCount, Node> {
|
||||
class ArrayCount : public Castable<ArrayCount, UniqueNode> {
|
||||
public:
|
||||
~ArrayCount() override;
|
||||
|
||||
/// @returns a hash of the array count.
|
||||
virtual size_t Hash() const = 0;
|
||||
|
||||
/// @param t other array count
|
||||
/// @returns true if this array count is equal to the given array count
|
||||
virtual bool Equals(const ArrayCount& t) const = 0;
|
||||
|
||||
/// @param symbols the symbol table
|
||||
/// @returns the friendly name for this array count
|
||||
virtual std::string FriendlyName(const SymbolTable& symbols) const = 0;
|
||||
|
@ -59,9 +52,9 @@ class ConstantArrayCount final : public Castable<ConstantArrayCount, ArrayCount>
|
|||
/// @returns a hash of the array count.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param t other array count
|
||||
/// @returns true if this array count is equal to the given array count
|
||||
bool Equals(const ArrayCount& t) const override;
|
||||
/// @param other the other object
|
||||
/// @returns true if this array count is equal to other
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @param symbols the symbol table
|
||||
/// @returns the friendly name for this array count
|
||||
|
@ -85,9 +78,9 @@ class RuntimeArrayCount final : public Castable<RuntimeArrayCount, ArrayCount> {
|
|||
/// @returns a hash of the array count.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param t other array count
|
||||
/// @returns true if this array count is equal to the given array count
|
||||
bool Equals(const ArrayCount& t) const override;
|
||||
/// @param other the other object
|
||||
/// @returns true if this array count is equal to other
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @param symbols the symbol table
|
||||
/// @returns the friendly name for this array count
|
||||
|
|
|
@ -35,7 +35,7 @@ size_t Atomic::Hash() const {
|
|||
return utils::Hash(TypeInfo::Of<Atomic>().full_hashcode, subtype_);
|
||||
}
|
||||
|
||||
bool Atomic::Equals(const type::Type& other) const {
|
||||
bool Atomic::Equals(const type::UniqueNode& other) const {
|
||||
if (auto* o = other.As<Atomic>()) {
|
||||
return o->subtype_ == subtype_;
|
||||
}
|
||||
|
|
|
@ -35,9 +35,9 @@ class Atomic final : public Castable<Atomic, Type> {
|
|||
/// @returns a hash of the type.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param other the other type to compare against
|
||||
/// @returns true if the this type is equal to the given type
|
||||
bool Equals(const type::Type& other) const override;
|
||||
/// @param other the other node to compare against
|
||||
/// @returns true if the this type is equal to @p other
|
||||
bool Equals(const type::UniqueNode& other) const override;
|
||||
|
||||
/// @returns the atomic type
|
||||
const type::Type* Type() const { return subtype_; }
|
||||
|
|
|
@ -35,7 +35,7 @@ size_t Bool::Hash() const {
|
|||
return static_cast<size_t>(TypeInfo::Of<Bool>().full_hashcode);
|
||||
}
|
||||
|
||||
bool Bool::Equals(const Type& other) const {
|
||||
bool Bool::Equals(const UniqueNode& other) const {
|
||||
return other.Is<Bool>();
|
||||
}
|
||||
|
||||
|
|
|
@ -39,9 +39,9 @@ class Bool final : public Castable<Bool, Type> {
|
|||
/// @returns a hash of the type.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param other the other type to compare against
|
||||
/// @returns true if the this type is equal to the given type
|
||||
bool Equals(const Type& other) const override;
|
||||
/// @param other the other node to compare against
|
||||
/// @returns true if the this type is equal to @p other
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
|
|
|
@ -40,7 +40,7 @@ size_t DepthMultisampledTexture::Hash() const {
|
|||
return utils::Hash(TypeInfo::Of<DepthMultisampledTexture>().full_hashcode, dim());
|
||||
}
|
||||
|
||||
bool DepthMultisampledTexture::Equals(const Type& other) const {
|
||||
bool DepthMultisampledTexture::Equals(const UniqueNode& other) const {
|
||||
if (auto* o = other.As<DepthMultisampledTexture>()) {
|
||||
return o->dim() == dim();
|
||||
}
|
||||
|
|
|
@ -34,9 +34,9 @@ class DepthMultisampledTexture final : public Castable<DepthMultisampledTexture,
|
|||
/// @returns a hash of the type.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param other the other type to compare against
|
||||
/// @returns true if the this type is equal to the given type
|
||||
bool Equals(const Type& other) const override;
|
||||
/// @param other the other node to compare against
|
||||
/// @returns true if the this type is equal to @p other
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
|
|
|
@ -41,7 +41,7 @@ size_t DepthTexture::Hash() const {
|
|||
return utils::Hash(TypeInfo::Of<DepthTexture>().full_hashcode, dim());
|
||||
}
|
||||
|
||||
bool DepthTexture::Equals(const Type& other) const {
|
||||
bool DepthTexture::Equals(const UniqueNode& other) const {
|
||||
if (auto* o = other.As<DepthTexture>()) {
|
||||
return o->dim() == dim();
|
||||
}
|
||||
|
|
|
@ -34,9 +34,9 @@ class DepthTexture final : public Castable<DepthTexture, Texture> {
|
|||
/// @returns a hash of the type.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param other the other type to compare against
|
||||
/// @returns true if the this type is equal to the given type
|
||||
bool Equals(const Type& other) const override;
|
||||
/// @param other the other node to compare against
|
||||
/// @returns true if the this type is equal to @p other
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
|
|
|
@ -30,7 +30,7 @@ size_t ExternalTexture::Hash() const {
|
|||
return static_cast<size_t>(TypeInfo::Of<ExternalTexture>().full_hashcode);
|
||||
}
|
||||
|
||||
bool ExternalTexture::Equals(const Type& other) const {
|
||||
bool ExternalTexture::Equals(const UniqueNode& other) const {
|
||||
return other.Is<ExternalTexture>();
|
||||
}
|
||||
|
||||
|
|
|
@ -34,9 +34,9 @@ class ExternalTexture final : public Castable<ExternalTexture, Texture> {
|
|||
/// @returns a hash of the type.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param other the other type to compare against
|
||||
/// @returns true if the this type is equal to the given type
|
||||
bool Equals(const Type& other) const override;
|
||||
/// @param other the other node to compare against
|
||||
/// @returns true if the this type is equal to @p other
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
|
|
|
@ -35,7 +35,7 @@ size_t F16::Hash() const {
|
|||
return static_cast<size_t>(TypeInfo::Of<F16>().full_hashcode);
|
||||
}
|
||||
|
||||
bool F16::Equals(const Type& other) const {
|
||||
bool F16::Equals(const UniqueNode& other) const {
|
||||
return other.Is<F16>();
|
||||
}
|
||||
|
||||
|
|
|
@ -33,9 +33,9 @@ class F16 final : public Castable<F16, Type> {
|
|||
/// @returns a hash of the type.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param other the other type to compare against
|
||||
/// @returns true if the this type is equal to the given type
|
||||
bool Equals(const Type& other) const override;
|
||||
/// @param other the other node to compare against
|
||||
/// @returns true if the this type is equal to @p other
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
|
|
|
@ -35,7 +35,7 @@ size_t F32::Hash() const {
|
|||
return static_cast<size_t>(TypeInfo::Of<F32>().full_hashcode);
|
||||
}
|
||||
|
||||
bool F32::Equals(const Type& other) const {
|
||||
bool F32::Equals(const UniqueNode& other) const {
|
||||
return other.Is<F32>();
|
||||
}
|
||||
|
||||
|
|
|
@ -33,9 +33,9 @@ class F32 final : public Castable<F32, Type> {
|
|||
/// @returns a hash of the type.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param other the other type to compare against
|
||||
/// @returns true if the this type is equal to the given type
|
||||
bool Equals(const Type& other) const override;
|
||||
/// @param other the other node to compare against
|
||||
/// @returns true if the this type is equal to @p other
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
|
|
|
@ -35,7 +35,7 @@ size_t I32::Hash() const {
|
|||
return static_cast<size_t>(TypeInfo::Of<I32>().full_hashcode);
|
||||
}
|
||||
|
||||
bool I32::Equals(const Type& other) const {
|
||||
bool I32::Equals(const UniqueNode& other) const {
|
||||
return other.Is<I32>();
|
||||
}
|
||||
|
||||
|
|
|
@ -33,9 +33,9 @@ class I32 final : public Castable<I32, Type> {
|
|||
/// @returns a hash of the type.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param other the other type to compare against
|
||||
/// @returns true if the this type is equal to the given type
|
||||
bool Equals(const Type& other) const override;
|
||||
/// @param other the other node to compare against
|
||||
/// @returns true if the this type is equal to @p other
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
|
|
|
@ -15,15 +15,10 @@
|
|||
#ifndef SRC_TINT_TYPE_MANAGER_H_
|
||||
#define SRC_TINT_TYPE_MANAGER_H_
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#include "src/tint/type/array_count.h"
|
||||
#include "src/tint/type/node.h"
|
||||
#include "src/tint/type/struct.h"
|
||||
#include "src/tint/type/type.h"
|
||||
#include "src/tint/utils/hash.h"
|
||||
#include "src/tint/utils/unique_allocator.h"
|
||||
|
||||
namespace tint::type {
|
||||
|
@ -60,19 +55,23 @@ class Manager final {
|
|||
static Manager Wrap(const Manager& inner) {
|
||||
Manager out;
|
||||
out.types_.Wrap(inner.types_);
|
||||
out.nodes_.Wrap(inner.nodes_);
|
||||
out.unique_nodes_.Wrap(inner.unique_nodes_);
|
||||
return out;
|
||||
}
|
||||
|
||||
/// @param args the arguments used to construct the object.
|
||||
/// @param args the arguments used to construct the type, unique node or node.
|
||||
/// @return a pointer to an instance of `T` with the provided arguments.
|
||||
/// If an existing instance of `T` has been constructed, then the same
|
||||
/// pointer is returned.
|
||||
template <typename TYPE,
|
||||
typename _ = std::enable_if<traits::IsTypeOrDerived<TYPE, Type>>,
|
||||
typename... ARGS>
|
||||
TYPE* Get(ARGS&&... args) {
|
||||
return types_.Get<TYPE>(std::forward<ARGS>(args)...);
|
||||
/// If NODE derives from UniqueNode and an existing instance of `T` has been
|
||||
/// constructed, then the same pointer is returned.
|
||||
template <typename NODE, typename... ARGS>
|
||||
NODE* Get(ARGS&&... args) {
|
||||
if constexpr (traits::IsTypeOrDerived<NODE, Type>) {
|
||||
return types_.Get<NODE>(std::forward<ARGS>(args)...);
|
||||
} else if constexpr (traits::IsTypeOrDerived<NODE, UniqueNode>) {
|
||||
return unique_nodes_.Get<NODE>(std::forward<ARGS>(args)...);
|
||||
} else {
|
||||
return nodes_.Create<NODE>(std::forward<ARGS>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
/// @param args the arguments used to create the temporary used for the search.
|
||||
|
@ -85,68 +84,20 @@ class Manager final {
|
|||
return types_.Find<TYPE>(std::forward<ARGS>(args)...);
|
||||
}
|
||||
|
||||
/// @param args the arguments used to construct the object.
|
||||
/// @return a pointer to an instance of `T` with the provided arguments.
|
||||
/// If an existing instance of `T` has been constructed, then the same
|
||||
/// pointer is returned.
|
||||
template <typename TYPE,
|
||||
typename _ = std::enable_if<traits::IsTypeOrDerived<TYPE, ArrayCount> ||
|
||||
traits::IsTypeOrDerived<TYPE, StructMember>>,
|
||||
typename... ARGS>
|
||||
TYPE* GetNode(ARGS&&... args) {
|
||||
return nodes_.Get<TYPE>(std::forward<ARGS>(args)...);
|
||||
}
|
||||
|
||||
/// @returns an iterator to the beginning of the types
|
||||
TypeIterator begin() const { return types_.begin(); }
|
||||
/// @returns an iterator to the end of the types
|
||||
TypeIterator end() const { return types_.end(); }
|
||||
|
||||
private:
|
||||
/// Unique types owned by the manager
|
||||
utils::UniqueAllocator<Type> types_;
|
||||
utils::UniqueAllocator<Node> nodes_;
|
||||
/// Unique nodes (excluding types) owned by the manager
|
||||
utils::UniqueAllocator<UniqueNode> unique_nodes_;
|
||||
/// Non-unique nodes owned by the manager
|
||||
utils::BlockAllocator<Node> nodes_;
|
||||
};
|
||||
|
||||
} // namespace tint::type
|
||||
|
||||
namespace std {
|
||||
|
||||
/// std::hash specialization for tint::type::Node
|
||||
template <>
|
||||
struct hash<tint::type::Node> {
|
||||
/// @param type the type to obtain a hash from
|
||||
/// @returns the hash of the type
|
||||
size_t operator()(const tint::type::Node& type) const {
|
||||
if (const auto* ac = type.As<tint::type::ArrayCount>()) {
|
||||
return ac->Hash();
|
||||
} else if (type.Is<tint::type::StructMember>()) {
|
||||
return tint::TypeInfo::Of<tint::type::StructMember>().full_hashcode;
|
||||
}
|
||||
TINT_ASSERT(Type, false && "Unreachable");
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
/// std::equal_to specialization for tint::type::Node
|
||||
template <>
|
||||
struct equal_to<tint::type::Node> {
|
||||
/// @param a the first type to compare
|
||||
/// @param b the second type to compare
|
||||
/// @returns true if the two types are equal
|
||||
bool operator()(const tint::type::Node& a, const tint::type::Node& b) const {
|
||||
if (const auto* ac = a.As<tint::type::ArrayCount>()) {
|
||||
if (const auto* bc = b.As<tint::type::ArrayCount>()) {
|
||||
return ac->Equals(*bc);
|
||||
}
|
||||
return false;
|
||||
} else if (a.Is<tint::type::StructMember>()) {
|
||||
return &a == &b;
|
||||
}
|
||||
TINT_ASSERT(Type, false && "Unreachable");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // SRC_TINT_TYPE_MANAGER_H_
|
||||
|
|
|
@ -46,7 +46,7 @@ size_t Matrix::Hash() const {
|
|||
return utils::Hash(TypeInfo::Of<Vector>().full_hashcode, rows_, columns_, column_type_);
|
||||
}
|
||||
|
||||
bool Matrix::Equals(const Type& other) const {
|
||||
bool Matrix::Equals(const UniqueNode& other) const {
|
||||
if (auto* v = other.As<Matrix>()) {
|
||||
return v->rows_ == rows_ && v->columns_ == columns_ && v->column_type_ == column_type_;
|
||||
}
|
||||
|
|
|
@ -40,9 +40,9 @@ class Matrix final : public Castable<Matrix, Type> {
|
|||
/// @returns a hash of the type.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param other the other type to compare against
|
||||
/// @returns true if the this type is equal to the given type
|
||||
bool Equals(const Type& other) const override;
|
||||
/// @param other the other node to compare against
|
||||
/// @returns true if the this type is equal to @p other
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @returns the type of the matrix
|
||||
const Type* type() const { return subtype_; }
|
||||
|
|
|
@ -34,7 +34,7 @@ size_t MultisampledTexture::Hash() const {
|
|||
return utils::Hash(TypeInfo::Of<MultisampledTexture>().full_hashcode, dim(), type_);
|
||||
}
|
||||
|
||||
bool MultisampledTexture::Equals(const Type& other) const {
|
||||
bool MultisampledTexture::Equals(const UniqueNode& other) const {
|
||||
if (auto* o = other.As<MultisampledTexture>()) {
|
||||
return o->dim() == dim() && o->type_ == type_;
|
||||
}
|
||||
|
|
|
@ -35,9 +35,9 @@ class MultisampledTexture final : public Castable<MultisampledTexture, Texture>
|
|||
/// @returns a hash of the type.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param other the other type to compare against
|
||||
/// @returns true if the this type is equal to the given type
|
||||
bool Equals(const Type& other) const override;
|
||||
/// @param other the other node to compare against
|
||||
/// @returns true if the this type is equal to @p other
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @returns the subtype of the sampled texture
|
||||
const Type* type() const { return type_; }
|
||||
|
|
|
@ -32,7 +32,7 @@ size_t Pointer::Hash() const {
|
|||
return utils::Hash(TypeInfo::Of<Pointer>().full_hashcode, address_space_, subtype_, access_);
|
||||
}
|
||||
|
||||
bool Pointer::Equals(const Type& other) const {
|
||||
bool Pointer::Equals(const UniqueNode& other) const {
|
||||
if (auto* o = other.As<Pointer>()) {
|
||||
return o->address_space_ == address_space_ && o->subtype_ == subtype_ &&
|
||||
o->access_ == access_;
|
||||
|
|
|
@ -39,9 +39,9 @@ class Pointer final : public Castable<Pointer, Type> {
|
|||
/// @returns a hash of the type.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param other the other type to compare against
|
||||
/// @returns true if the this type is equal to the given type
|
||||
bool Equals(const Type& other) const override;
|
||||
/// @param other the other node to compare against
|
||||
/// @returns true if the this type is equal to @p other
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @returns the pointee type
|
||||
const Type* StoreType() const { return subtype_; }
|
||||
|
|
|
@ -31,7 +31,7 @@ size_t Reference::Hash() const {
|
|||
return utils::Hash(TypeInfo::Of<Reference>().full_hashcode, address_space_, subtype_, access_);
|
||||
}
|
||||
|
||||
bool Reference::Equals(const Type& other) const {
|
||||
bool Reference::Equals(const UniqueNode& other) const {
|
||||
if (auto* o = other.As<Reference>()) {
|
||||
return o->address_space_ == address_space_ && o->subtype_ == subtype_ &&
|
||||
o->access_ == access_;
|
||||
|
|
|
@ -39,9 +39,9 @@ class Reference final : public Castable<Reference, Type> {
|
|||
/// @returns a hash of the type.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param other the other type to compare against
|
||||
/// @returns true if the this type is equal to the given type
|
||||
bool Equals(const Type& other) const override;
|
||||
/// @param other the other node to compare against
|
||||
/// @returns true if the this type is equal to @p other
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @returns the pointee type
|
||||
const Type* StoreType() const { return subtype_; }
|
||||
|
|
|
@ -34,7 +34,7 @@ size_t SampledTexture::Hash() const {
|
|||
return utils::Hash(TypeInfo::Of<SampledTexture>().full_hashcode, dim(), type_);
|
||||
}
|
||||
|
||||
bool SampledTexture::Equals(const Type& other) const {
|
||||
bool SampledTexture::Equals(const UniqueNode& other) const {
|
||||
if (auto* o = other.As<SampledTexture>()) {
|
||||
return o->dim() == dim() && o->type_ == type_;
|
||||
}
|
||||
|
|
|
@ -35,9 +35,9 @@ class SampledTexture final : public Castable<SampledTexture, Texture> {
|
|||
/// @returns a hash of the type.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param other the other type to compare against
|
||||
/// @returns true if the this type is equal to the given type
|
||||
bool Equals(const Type& other) const override;
|
||||
/// @param other the other node to compare against
|
||||
/// @returns true if the this type is equal to @p other
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @returns the subtype of the sampled texture
|
||||
Type* type() const { return const_cast<Type*>(type_); }
|
||||
|
|
|
@ -31,7 +31,7 @@ size_t Sampler::Hash() const {
|
|||
return utils::Hash(TypeInfo::Of<Sampler>().full_hashcode, kind_);
|
||||
}
|
||||
|
||||
bool Sampler::Equals(const Type& other) const {
|
||||
bool Sampler::Equals(const UniqueNode& other) const {
|
||||
if (auto* o = other.As<Sampler>()) {
|
||||
return o->kind_ == kind_;
|
||||
}
|
||||
|
|
|
@ -35,9 +35,9 @@ class Sampler final : public Castable<Sampler, Type> {
|
|||
/// @returns a hash of the type.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param other the other type to compare against
|
||||
/// @returns true if the this type is equal to the given type
|
||||
bool Equals(const Type& other) const override;
|
||||
/// @param other the other node to compare against
|
||||
/// @returns true if the this type is equal to @p other
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @returns the sampler type
|
||||
ast::SamplerKind kind() const { return kind_; }
|
||||
|
|
|
@ -35,7 +35,7 @@ size_t StorageTexture::Hash() const {
|
|||
return utils::Hash(TypeInfo::Of<StorageTexture>().full_hashcode, dim(), texel_format_, access_);
|
||||
}
|
||||
|
||||
bool StorageTexture::Equals(const Type& other) const {
|
||||
bool StorageTexture::Equals(const UniqueNode& other) const {
|
||||
if (auto* o = other.As<StorageTexture>()) {
|
||||
return o->dim() == dim() && o->texel_format_ == texel_format_ && o->access_ == access_;
|
||||
}
|
||||
|
|
|
@ -48,9 +48,9 @@ class StorageTexture final : public Castable<StorageTexture, Texture> {
|
|||
/// @returns a hash of the type.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param other the other type to compare against
|
||||
/// @returns true if the this type is equal to the given type
|
||||
bool Equals(const Type& other) const override;
|
||||
/// @param other the other node to compare against
|
||||
/// @returns true if the this type is equal to @p other
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @returns the storage subtype
|
||||
Type* type() const { return subtype_; }
|
||||
|
|
|
@ -70,7 +70,7 @@ size_t Struct::Hash() const {
|
|||
return utils::Hash(TypeInfo::Of<Struct>().full_hashcode, name_);
|
||||
}
|
||||
|
||||
bool Struct::Equals(const Type& other) const {
|
||||
bool Struct::Equals(const UniqueNode& other) const {
|
||||
if (auto* o = other.As<Struct>()) {
|
||||
return o->name_ == name_;
|
||||
}
|
||||
|
|
|
@ -68,9 +68,9 @@ class Struct : public Castable<Struct, Type> {
|
|||
/// @returns a hash of the type.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param other the other type to compare against
|
||||
/// @returns true if the this type is equal to the given type
|
||||
bool Equals(const Type& other) const override;
|
||||
/// @param other the other node to compare against
|
||||
/// @returns true if the this type is equal to @p other
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @returns the source of the structure
|
||||
tint::Source Source() const { return source_; }
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "src/tint/type/node.h"
|
||||
#include "src/tint/type/unique_node.h"
|
||||
#include "src/tint/utils/enum_set.h"
|
||||
#include "src/tint/utils/vector.h"
|
||||
|
||||
|
@ -46,18 +46,12 @@ enum Flag {
|
|||
using Flags = utils::EnumSet<Flag>;
|
||||
|
||||
/// Base class for a type in the system
|
||||
class Type : public Castable<Type, Node> {
|
||||
class Type : public Castable<Type, UniqueNode> {
|
||||
public:
|
||||
/// Move constructor
|
||||
Type(Type&&);
|
||||
~Type() override;
|
||||
|
||||
/// @returns a hash of the type.
|
||||
virtual size_t Hash() const = 0;
|
||||
|
||||
/// @returns true if the this type is equal to the given type
|
||||
virtual bool Equals(const Type&) const = 0;
|
||||
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
/// declared in WGSL.
|
||||
|
|
|
@ -35,7 +35,7 @@ size_t U32::Hash() const {
|
|||
return static_cast<size_t>(TypeInfo::Of<U32>().full_hashcode);
|
||||
}
|
||||
|
||||
bool U32::Equals(const Type& other) const {
|
||||
bool U32::Equals(const UniqueNode& other) const {
|
||||
return other.Is<U32>();
|
||||
}
|
||||
|
||||
|
|
|
@ -33,9 +33,9 @@ class U32 final : public Castable<U32, Type> {
|
|||
/// @returns a hash of the type.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param other the other type to compare against
|
||||
/// @returns true if the this type is equal to the given type
|
||||
bool Equals(const Type& other) const override;
|
||||
/// @param other the other node to compare against
|
||||
/// @returns true if the this type is equal to @p other
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2022 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/tint/type/unique_node.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::type::UniqueNode);
|
||||
|
||||
namespace tint::type {
|
||||
|
||||
UniqueNode::UniqueNode() = default;
|
||||
|
||||
UniqueNode::UniqueNode(const UniqueNode&) = default;
|
||||
|
||||
UniqueNode::~UniqueNode() = default;
|
||||
|
||||
} // namespace tint::type
|
|
@ -0,0 +1,72 @@
|
|||
// Copyright 2022 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SRC_TINT_TYPE_UNIQUE_NODE_H_
|
||||
#define SRC_TINT_TYPE_UNIQUE_NODE_H_
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "src/tint/type/node.h"
|
||||
|
||||
namespace tint::type {
|
||||
|
||||
/// UniqueNode is the base class for objects that are de-duplicated by the Manager.
|
||||
/// Deduplication is achieved by comparing a temporary object to the set of existing objects, using
|
||||
/// Hash() and Equals(). If an existing object is found, then the pointer to that object is
|
||||
/// returned, otherwise a new object is constructed, added to the Manager's set and returned.
|
||||
class UniqueNode : public Castable<UniqueNode, Node> {
|
||||
public:
|
||||
/// Constructor
|
||||
UniqueNode();
|
||||
|
||||
/// Copy constructor
|
||||
UniqueNode(const UniqueNode&);
|
||||
|
||||
/// Destructor
|
||||
~UniqueNode() override;
|
||||
|
||||
/// @returns a hash of the node.
|
||||
virtual size_t Hash() const = 0;
|
||||
|
||||
/// @param other the other node to compare this node against
|
||||
/// @returns true if the this node is equal to @p other
|
||||
virtual bool Equals(const UniqueNode& other) const = 0;
|
||||
};
|
||||
|
||||
} // namespace tint::type
|
||||
|
||||
namespace std {
|
||||
|
||||
/// std::hash specialization for tint::type::UniqueNode
|
||||
template <>
|
||||
struct hash<tint::type::UniqueNode> {
|
||||
/// @param node the unique node to obtain a hash from
|
||||
/// @returns the hash of the node
|
||||
size_t operator()(const tint::type::UniqueNode& node) const { return node.Hash(); }
|
||||
};
|
||||
|
||||
/// std::equal_to specialization for tint::type::UniqueNode
|
||||
template <>
|
||||
struct equal_to<tint::type::UniqueNode> {
|
||||
/// @param a the first unique node to compare
|
||||
/// @param b the second unique node to compare
|
||||
/// @returns true if the two nodes are equal
|
||||
bool operator()(const tint::type::UniqueNode& a, const tint::type::UniqueNode& b) const {
|
||||
return &a == &b || a.Equals(b);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // SRC_TINT_TYPE_UNIQUE_NODE_H_
|
|
@ -41,7 +41,7 @@ size_t Vector::Hash() const {
|
|||
return utils::Hash(TypeInfo::Of<Vector>().full_hashcode, width_, subtype_);
|
||||
}
|
||||
|
||||
bool Vector::Equals(const Type& other) const {
|
||||
bool Vector::Equals(const UniqueNode& other) const {
|
||||
if (auto* v = other.As<Vector>()) {
|
||||
return v->width_ == width_ && v->subtype_ == subtype_;
|
||||
}
|
||||
|
|
|
@ -35,9 +35,9 @@ class Vector final : public Castable<Vector, Type> {
|
|||
/// @returns a hash of the type.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param other the other type to compare against
|
||||
/// @returns true if the this type is equal to the given type
|
||||
bool Equals(const Type& other) const override;
|
||||
/// @param other the other node to compare against
|
||||
/// @returns true if the this type is equal to @p other
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @returns the type of the vector elements
|
||||
const Type* type() const { return subtype_; }
|
||||
|
|
|
@ -30,7 +30,7 @@ size_t Void::Hash() const {
|
|||
return static_cast<size_t>(TypeInfo::Of<Void>().full_hashcode);
|
||||
}
|
||||
|
||||
bool Void::Equals(const Type& other) const {
|
||||
bool Void::Equals(const UniqueNode& other) const {
|
||||
return other.Is<Void>();
|
||||
}
|
||||
|
||||
|
|
|
@ -33,9 +33,9 @@ class Void final : public Castable<Void, Type> {
|
|||
/// @returns a hash of the type.
|
||||
size_t Hash() const override;
|
||||
|
||||
/// @param other the other type to compare against
|
||||
/// @returns true if the this type is equal to the given type
|
||||
bool Equals(const Type& other) const override;
|
||||
/// @param other the other node to compare against
|
||||
/// @returns true if the this type is equal to @p other
|
||||
bool Equals(const UniqueNode& other) const override;
|
||||
|
||||
/// @param symbols the program's symbol table
|
||||
/// @returns the name for this type that closely resembles how it would be
|
||||
|
|
Loading…
Reference in New Issue