| // 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_TYPE_H_ |
| #define SRC_TINT_TYPE_TYPE_H_ |
| |
| #include <functional> |
| #include <string> |
| |
| #include "src/tint/type/clone_context.h" |
| #include "src/tint/type/unique_node.h" |
| #include "src/tint/utils/enum_set.h" |
| #include "src/tint/utils/vector.h" |
| |
| // Forward declarations |
| namespace tint { |
| class ProgramBuilder; |
| class SymbolTable; |
| } // namespace tint |
| |
| namespace tint::type { |
| |
| enum Flag { |
| /// Type is constructable. |
| /// @see https://gpuweb.github.io/gpuweb/wgsl/#constructible-types |
| kConstructable, |
| /// Type has a creation-fixed footprint. |
| /// @see https://www.w3.org/TR/WGSL/#fixed-footprint-types |
| kCreationFixedFootprint, |
| /// Type has a fixed footprint. |
| /// @see https://www.w3.org/TR/WGSL/#fixed-footprint-types |
| kFixedFootprint, |
| }; |
| |
| /// An alias to utils::EnumSet<Flag> |
| using Flags = utils::EnumSet<Flag>; |
| |
| /// Base class for a type in the system |
| class Type : public Castable<Type, UniqueNode> { |
| public: |
| /// Destructor |
| ~Type() override; |
| |
| /// @param symbols the program's symbol table |
| /// @returns the name for this type that closely resembles how it would be |
| /// declared in WGSL. |
| virtual std::string FriendlyName(const SymbolTable& symbols) const = 0; |
| |
| /// @returns the inner most pointee type if this is a pointer, `this` |
| /// otherwise |
| const Type* UnwrapPtr() const; |
| |
| /// @returns the inner type if this is a reference, `this` otherwise |
| const Type* UnwrapRef() const; |
| |
| /// @returns the size in bytes of the type. This may include tail padding. |
| /// @note opaque types will return a size of 0. |
| virtual uint32_t Size() const; |
| |
| /// @returns the alignment in bytes of the type. This may include tail |
| /// padding. |
| /// @note opaque types will return a size of 0. |
| virtual uint32_t Align() const; |
| |
| /// @param ctx the clone context |
| /// @returns a clone of this type created in the provided context |
| virtual Type* Clone(CloneContext& ctx) const = 0; |
| |
| /// @returns the flags on the type |
| type::Flags Flags() { return flags_; } |
| |
| /// @returns true if type is constructable |
| /// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types |
| inline bool IsConstructible() const { return flags_.Contains(Flag::kConstructable); } |
| |
| /// @returns true has a creation-fixed footprint. |
| /// @see https://www.w3.org/TR/WGSL/#fixed-footprint-types |
| inline bool HasCreationFixedFootprint() const { |
| return flags_.Contains(Flag::kCreationFixedFootprint); |
| } |
| |
| /// @returns true has a fixed footprint. |
| /// @see https://www.w3.org/TR/WGSL/#fixed-footprint-types |
| inline bool HasFixedFootprint() const { return flags_.Contains(Flag::kFixedFootprint); } |
| |
| /// @returns true if this type is a scalar |
| bool is_scalar() const; |
| /// @returns true if this type is a numeric scalar |
| bool is_numeric_scalar() const; |
| /// @returns true if this type is a float scalar |
| bool is_float_scalar() const; |
| /// @returns true if this type is a float matrix |
| bool is_float_matrix() const; |
| /// @returns true if this type is a square float matrix |
| bool is_square_float_matrix() const; |
| /// @returns true if this type is a float vector |
| bool is_float_vector() const; |
| /// @returns true if this type is a float scalar or vector |
| bool is_float_scalar_or_vector() const; |
| /// @returns true if this type is a float scalar or vector or matrix |
| bool is_float_scalar_or_vector_or_matrix() const; |
| /// @returns true if this type is an integer scalar |
| bool is_integer_scalar() const; |
| /// @returns true if this type is a signed integer scalar |
| bool is_signed_integer_scalar() const; |
| /// @returns true if this type is an unsigned integer scalar |
| bool is_unsigned_integer_scalar() const; |
| /// @returns true if this type is a signed integer vector |
| bool is_signed_integer_vector() const; |
| /// @returns true if this type is an unsigned vector |
| bool is_unsigned_integer_vector() const; |
| /// @returns true if this type is an unsigned scalar or vector |
| bool is_unsigned_integer_scalar_or_vector() const; |
| /// @returns true if this type is a signed scalar or vector |
| bool is_signed_integer_scalar_or_vector() const; |
| /// @returns true if this type is an integer scalar or vector |
| bool is_integer_scalar_or_vector() const; |
| /// @returns true if this type is an abstract integer vector |
| bool is_abstract_integer_vector() const; |
| /// @returns true if this type is an abstract float vector |
| bool is_abstract_float_vector() const; |
| /// @returns true if this type is an abstract integer scalar or vector |
| bool is_abstract_integer_scalar_or_vector() const; |
| /// @returns true if this type is an abstract float scalar or vector |
| bool is_abstract_float_scalar_or_vector() const; |
| /// @returns true if this type is a boolean vector |
| bool is_bool_vector() const; |
| /// @returns true if this type is boolean scalar or vector |
| bool is_bool_scalar_or_vector() const; |
| /// @returns true if this type is a numeric vector |
| bool is_numeric_vector() const; |
| /// @returns true if this type is a vector of scalar type |
| bool is_scalar_vector() const; |
| /// @returns true if this type is a numeric scale or vector |
| bool is_numeric_scalar_or_vector() const; |
| /// @returns true if this type is a handle type |
| bool is_handle() const; |
| |
| /// @returns true if this type is an abstract-numeric or if the type holds an element that is an |
| /// abstract-numeric. |
| bool HoldsAbstract() const; |
| |
| /// kNoConversion is returned from ConversionRank() when the implicit conversion is not |
| /// permitted. |
| static constexpr uint32_t kNoConversion = 0xffffffffu; |
| |
| /// ConversionRank returns the implicit conversion rank when attempting to convert `from` to |
| /// `to`. Lower ranks are preferred over higher ranks. |
| /// @param from the source type |
| /// @param to the destination type |
| /// @returns the rank value for converting from type `from` to type `to`, or #kNoConversion if |
| /// the implicit conversion is not allowed. |
| /// @see https://www.w3.org/TR/WGSL/#conversion-rank |
| static uint32_t ConversionRank(const Type* from, const Type* to); |
| |
| /// @param ty the type to obtain the element type from |
| /// @param count if not null, then this is assigned the number of child elements in the type. |
| /// For example, the count of an `array<vec3<f32>, 5>` type would be 5. |
| /// @returns |
| /// * the element type if `ty` is a vector or array |
| /// * the column type if `ty` is a matrix |
| /// * `ty` if `ty` is none of the above |
| static const Type* ElementOf(const Type* ty, uint32_t* count = nullptr); |
| |
| /// @param ty the type to obtain the deepest element type from |
| /// @param count if not null, then this is assigned the full number of most deeply nested |
| /// elements in the type. For example, the count of an `array<vec3<f32>, 5>` type would be 15. |
| /// @returns |
| /// * the element type if `ty` is a vector |
| /// * the matrix element type if `ty` is a matrix |
| /// * the deepest element type if `ty` is an array |
| /// * `ty` if `ty` is none of the above |
| static const Type* DeepestElementOf(const Type* ty, uint32_t* count = nullptr); |
| |
| /// @param types the list of types |
| /// @returns the lowest-ranking type that all types in `types` can be implicitly converted to, |
| /// or nullptr if there is no consistent common type across all types in `types`. |
| /// @see https://www.w3.org/TR/WGSL/#conversion-rank |
| static const Type* Common(utils::VectorRef<const Type*> types); |
| |
| protected: |
| /// Constructor |
| /// @param hash the immutable hash for the node |
| /// @param flags the flags of this type |
| Type(size_t hash, type::Flags flags); |
| |
| /// The flags of this type. |
| const type::Flags flags_; |
| }; |
| |
| } // namespace tint::type |
| |
| namespace std { |
| |
| /// std::hash specialization for tint::type::Type |
| template <> |
| struct hash<tint::type::Type> { |
| /// @param type the type to obtain a hash from |
| /// @returns the hash of the type |
| size_t operator()(const tint::type::Type& type) const { return type.unique_hash; } |
| }; |
| |
| /// std::equal_to specialization for tint::type::Type |
| template <> |
| struct equal_to<tint::type::Type> { |
| /// @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::Type& a, const tint::type::Type& b) const { |
| return a.Equals(b); |
| } |
| }; |
| |
| } // namespace std |
| |
| #endif // SRC_TINT_TYPE_TYPE_H_ |