Move type base classes into type/ folder.

This CL moves sem/type and copies sem/node into the type/ folder. The
type subclasses are moved over to using type::Type while remaining in
the sem:: namespace. They will be moved over in followup CLs.

Bug: tint:1718
Change-Id: I3f3495328d734f88e4fc2dfbc6705343f1198dc5
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/113180
Reviewed-by: Ben Clayton <bclayton@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
dan sinclair
2022-12-08 00:32:27 +00:00
committed by Dawn LUCI CQ
parent ad71dc1ab2
commit 5f764d8527
148 changed files with 1895 additions and 1657 deletions

View File

@@ -0,0 +1,51 @@
// 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/array_count.h"
TINT_INSTANTIATE_TYPEINFO(tint::type::ArrayCount);
TINT_INSTANTIATE_TYPEINFO(tint::type::ConstantArrayCount);
TINT_INSTANTIATE_TYPEINFO(tint::type::RuntimeArrayCount);
namespace tint::type {
ArrayCount::ArrayCount() : Base() {}
ArrayCount::~ArrayCount() = default;
ConstantArrayCount::ConstantArrayCount(uint32_t val) : Base(), value(val) {}
ConstantArrayCount::~ConstantArrayCount() = default;
size_t ConstantArrayCount::Hash() const {
return static_cast<size_t>(TypeInfo::Of<ConstantArrayCount>().full_hashcode);
}
bool ConstantArrayCount::Equals(const ArrayCount& other) const {
if (auto* v = other.As<ConstantArrayCount>()) {
return value == v->value;
}
return false;
}
RuntimeArrayCount::RuntimeArrayCount() : Base() {}
RuntimeArrayCount::~RuntimeArrayCount() = default;
size_t RuntimeArrayCount::Hash() const {
return static_cast<size_t>(TypeInfo::Of<RuntimeArrayCount>().full_hashcode);
}
bool RuntimeArrayCount::Equals(const ArrayCount& other) const {
return other.Is<RuntimeArrayCount>();
}
} // namespace tint::type

108
src/tint/type/array_count.h Normal file
View File

@@ -0,0 +1,108 @@
// 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_ARRAY_COUNT_H_
#define SRC_TINT_TYPE_ARRAY_COUNT_H_
#include <functional>
#include "src/tint/type/node.h"
namespace tint::type {
/// An array count
class ArrayCount : public Castable<ArrayCount, Node> {
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;
protected:
ArrayCount();
};
/// The variant of an ArrayCount when the array is a const-expression.
/// Example:
/// ```
/// const N = 123;
/// type arr = array<i32, N>
/// ```
class ConstantArrayCount final : public Castable<ConstantArrayCount, ArrayCount> {
public:
/// Constructor
/// @param val the constant-expression value
explicit ConstantArrayCount(uint32_t val);
~ConstantArrayCount() override;
/// @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;
/// The array count constant-expression value.
uint32_t value;
};
/// The variant of an ArrayCount when the array is is runtime-sized.
/// Example:
/// ```
/// type arr = array<i32>
/// ```
class RuntimeArrayCount final : public Castable<RuntimeArrayCount, ArrayCount> {
public:
/// Constructor
RuntimeArrayCount();
~RuntimeArrayCount() override;
/// @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;
};
} // namespace tint::type
namespace std {
/// std::hash specialization for tint::type::ArrayCount
template <>
struct hash<tint::type::ArrayCount> {
/// @param a the array count to obtain a hash from
/// @returns the hash of the array count
size_t operator()(const tint::type::ArrayCount& a) const { return a.Hash(); }
};
/// std::equal_to specialization for tint::type::ArrayCount
template <>
struct equal_to<tint::type::ArrayCount> {
/// @param a the first array count to compare
/// @param b the second array count to compare
/// @returns true if the two array counts are equal
bool operator()(const tint::type::ArrayCount& a, const tint::type::ArrayCount& b) const {
return a.Equals(b);
}
};
} // namespace std
#endif // SRC_TINT_TYPE_ARRAY_COUNT_H_

27
src/tint/type/node.cc Normal file
View File

@@ -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/node.h"
TINT_INSTANTIATE_TYPEINFO(tint::type::Node);
namespace tint::type {
Node::Node() = default;
Node::Node(const Node&) = default;
Node::~Node() = default;
} // namespace tint::type

37
src/tint/type/node.h Normal file
View File

@@ -0,0 +1,37 @@
// 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_NODE_H_
#define SRC_TINT_TYPE_NODE_H_
#include "src/tint/castable.h"
namespace tint::type {
/// Node is the base class for all type nodes
class Node : public Castable<Node> {
public:
/// Constructor
Node();
/// Copy constructor
Node(const Node&);
/// Destructor
~Node() override;
};
} // namespace tint::type
#endif // SRC_TINT_TYPE_NODE_H_

View File

@@ -0,0 +1,59 @@
// 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_TEST_HELPER_H_
#define SRC_TINT_TYPE_TEST_HELPER_H_
#include <utility>
#include "gtest/gtest.h"
#include "src/tint/program_builder.h"
namespace tint::type {
/// Helper class for testing
template <typename BASE>
class TestHelperBase : public BASE, public ProgramBuilder {
public:
/// Builds and returns the program. Must only be called once per test
/// @return the built program
Program Build() {
diag::Formatter formatter;
[&]() {
ASSERT_TRUE(IsValid()) << "Builder program is not valid\n"
<< formatter.format(Diagnostics());
}();
return Program(std::move(*this));
}
};
using TestHelper = TestHelperBase<testing::Test>;
template <typename T>
using TestParamHelper = TestHelperBase<testing::TestWithParam<T>>;
} // namespace tint::type
/// Helper macro for testing that a type was as expected
#define EXPECT_TYPE(GOT, EXPECT) \
do { \
const type::Type* got = GOT; \
const type::Type* expect = EXPECT; \
if (got != expect) { \
ADD_FAILURE() << #GOT " != " #EXPECT "\n" \
<< " " #GOT ": " << FriendlyName(got) << "\n" \
<< " " #EXPECT ": " << FriendlyName(expect); \
} \
} while (false)
#endif // SRC_TINT_TYPE_TEST_HELPER_H_

329
src/tint/type/type.cc Normal file
View File

@@ -0,0 +1,329 @@
// Copyright 2020 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/type.h"
#include "src/tint/sem/abstract_float.h"
#include "src/tint/sem/abstract_int.h"
#include "src/tint/sem/array.h"
#include "src/tint/sem/bool.h"
#include "src/tint/sem/f16.h"
#include "src/tint/sem/f32.h"
#include "src/tint/sem/i32.h"
#include "src/tint/sem/matrix.h"
#include "src/tint/sem/pointer.h"
#include "src/tint/sem/reference.h"
#include "src/tint/sem/sampler.h"
#include "src/tint/sem/struct.h"
#include "src/tint/sem/texture.h"
#include "src/tint/sem/u32.h"
#include "src/tint/sem/vector.h"
TINT_INSTANTIATE_TYPEINFO(tint::type::Type);
namespace tint::type {
Type::Type(TypeFlags flags) : flags_(flags) {
if (IsConstructible()) {
TINT_ASSERT(Type, HasCreationFixedFootprint());
}
}
Type::Type(Type&&) = default;
Type::~Type() = default;
const Type* Type::UnwrapPtr() const {
auto* type = this;
while (auto* ptr = type->As<sem::Pointer>()) {
type = ptr->StoreType();
}
return type;
}
const Type* Type::UnwrapRef() const {
auto* type = this;
if (auto* ref = type->As<sem::Reference>()) {
type = ref->StoreType();
}
return type;
}
uint32_t Type::Size() const {
return 0;
}
uint32_t Type::Align() const {
return 0;
}
bool Type::is_scalar() const {
return IsAnyOf<sem::F16, sem::F32, sem::U32, sem::I32, sem::AbstractNumeric, sem::Bool>();
}
bool Type::is_numeric_scalar() const {
return IsAnyOf<sem::F16, sem::F32, sem::U32, sem::I32, sem::AbstractNumeric>();
}
bool Type::is_float_scalar() const {
return IsAnyOf<sem::F16, sem::F32, sem::AbstractNumeric>();
}
bool Type::is_float_matrix() const {
return Is([](const sem::Matrix* m) { return m->type()->is_float_scalar(); });
}
bool Type::is_square_float_matrix() const {
return Is([](const sem::Matrix* m) {
return m->type()->is_float_scalar() && m->rows() == m->columns();
});
}
bool Type::is_float_vector() const {
return Is([](const sem::Vector* v) { return v->type()->is_float_scalar(); });
}
bool Type::is_float_scalar_or_vector() const {
return is_float_scalar() || is_float_vector();
}
bool Type::is_float_scalar_or_vector_or_matrix() const {
return is_float_scalar() || is_float_vector() || is_float_matrix();
}
bool Type::is_integer_scalar() const {
return IsAnyOf<sem::U32, sem::I32>();
}
bool Type::is_signed_integer_scalar() const {
return IsAnyOf<sem::I32, sem::AbstractInt>();
}
bool Type::is_unsigned_integer_scalar() const {
return Is<sem::U32>();
}
bool Type::is_signed_integer_vector() const {
return Is(
[](const sem::Vector* v) { return v->type()->IsAnyOf<sem::I32, sem::AbstractInt>(); });
}
bool Type::is_unsigned_integer_vector() const {
return Is([](const sem::Vector* v) { return v->type()->Is<sem::U32>(); });
}
bool Type::is_unsigned_integer_scalar_or_vector() const {
return Is<sem::U32>() || is_unsigned_integer_vector();
}
bool Type::is_signed_integer_scalar_or_vector() const {
return IsAnyOf<sem::I32, sem::AbstractInt>() || is_signed_integer_vector();
}
bool Type::is_integer_scalar_or_vector() const {
return is_unsigned_integer_scalar_or_vector() || is_signed_integer_scalar_or_vector();
}
bool Type::is_abstract_integer_vector() const {
return Is([](const sem::Vector* v) { return v->type()->Is<sem::AbstractInt>(); });
}
bool Type::is_abstract_float_vector() const {
return Is([](const sem::Vector* v) { return v->type()->Is<sem::AbstractFloat>(); });
}
bool Type::is_abstract_integer_scalar_or_vector() const {
return Is<sem::AbstractInt>() || is_abstract_integer_vector();
}
bool Type::is_abstract_float_scalar_or_vector() const {
return Is<sem::AbstractFloat>() || is_abstract_float_vector();
}
bool Type::is_bool_vector() const {
return Is([](const sem::Vector* v) { return v->type()->Is<sem::Bool>(); });
}
bool Type::is_bool_scalar_or_vector() const {
return Is<sem::Bool>() || is_bool_vector();
}
bool Type::is_numeric_vector() const {
return Is([](const sem::Vector* v) { return v->type()->is_numeric_scalar(); });
}
bool Type::is_scalar_vector() const {
return Is([](const sem::Vector* v) { return v->type()->is_scalar(); });
}
bool Type::is_numeric_scalar_or_vector() const {
return is_numeric_scalar() || is_numeric_vector();
}
bool Type::is_handle() const {
return IsAnyOf<sem::Sampler, sem::Texture>();
}
bool Type::HoldsAbstract() const {
return Switch(
this, //
[&](const sem::AbstractNumeric*) { return true; },
[&](const sem::Vector* v) { return v->type()->HoldsAbstract(); },
[&](const sem::Matrix* m) { return m->type()->HoldsAbstract(); },
[&](const sem::Array* a) { return a->ElemType()->HoldsAbstract(); },
[&](const sem::Struct* s) {
for (auto* m : s->Members()) {
if (m->Type()->HoldsAbstract()) {
return true;
}
}
return false;
});
}
uint32_t Type::ConversionRank(const Type* from, const Type* to) {
if (from->UnwrapRef() == to) {
return 0;
}
return Switch(
from,
[&](const sem::AbstractFloat*) {
return Switch(
to, //
[&](const sem::F32*) { return 1; }, //
[&](const sem::F16*) { return 2; }, //
[&](Default) { return kNoConversion; });
},
[&](const sem::AbstractInt*) {
return Switch(
to, //
[&](const sem::I32*) { return 3; }, //
[&](const sem::U32*) { return 4; }, //
[&](const sem::AbstractFloat*) { return 5; }, //
[&](const sem::F32*) { return 6; }, //
[&](const sem::F16*) { return 7; }, //
[&](Default) { return kNoConversion; });
},
[&](const sem::Vector* from_vec) {
if (auto* to_vec = to->As<sem::Vector>()) {
if (from_vec->Width() == to_vec->Width()) {
return ConversionRank(from_vec->type(), to_vec->type());
}
}
return kNoConversion;
},
[&](const sem::Matrix* from_mat) {
if (auto* to_mat = to->As<sem::Matrix>()) {
if (from_mat->columns() == to_mat->columns() &&
from_mat->rows() == to_mat->rows()) {
return ConversionRank(from_mat->type(), to_mat->type());
}
}
return kNoConversion;
},
[&](const sem::Array* from_arr) {
if (auto* to_arr = to->As<sem::Array>()) {
if (from_arr->Count() == to_arr->Count()) {
return ConversionRank(from_arr->ElemType(), to_arr->ElemType());
}
}
return kNoConversion;
},
[&](const sem::Struct* from_str) {
auto concrete_tys = from_str->ConcreteTypes();
for (size_t i = 0; i < concrete_tys.Length(); i++) {
if (concrete_tys[i] == to) {
return static_cast<uint32_t>(i + 1);
}
}
return kNoConversion;
},
[&](Default) { return kNoConversion; });
}
const Type* Type::ElementOf(const Type* ty, uint32_t* count /* = nullptr */) {
if (ty->is_scalar()) {
if (count) {
*count = 1;
}
return ty;
}
return Switch(
ty, //
[&](const sem::Vector* v) {
if (count) {
*count = v->Width();
}
return v->type();
},
[&](const sem::Matrix* m) {
if (count) {
*count = m->columns();
}
return m->ColumnType();
},
[&](const sem::Array* a) {
if (count) {
if (auto* const_count = a->Count()->As<type::ConstantArrayCount>()) {
*count = const_count->value;
}
}
return a->ElemType();
},
[&](Default) {
if (count) {
*count = 1;
}
return ty;
});
}
const Type* Type::DeepestElementOf(const Type* ty, uint32_t* count /* = nullptr */) {
auto el_ty = ElementOf(ty, count);
while (el_ty && ty != el_ty) {
ty = el_ty;
uint32_t n = 0;
el_ty = ElementOf(ty, &n);
if (count) {
*count *= n;
}
}
return el_ty;
}
const type::Type* Type::Common(utils::VectorRef<const Type*> types) {
const auto count = types.Length();
if (count == 0) {
return nullptr;
}
const auto* common = types[0];
for (size_t i = 1; i < count; i++) {
auto* ty = types[i];
if (ty == common) {
continue; // ty == common
}
if (type::Type::ConversionRank(ty, common) != type::Type::kNoConversion) {
continue; // ty can be converted to common.
}
if (type::Type::ConversionRank(common, ty) != type::Type::kNoConversion) {
common = ty; // common can be converted to ty.
continue;
}
return nullptr; // Conversion is not valid.
}
return common;
}
} // namespace tint::type

231
src/tint/type/type.h Normal file
View File

@@ -0,0 +1,231 @@
// 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/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 TypeFlag {
/// 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<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;
/// @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.
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;
/// @returns the flags on the type
TypeFlags 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::Type* Common(utils::VectorRef<const Type*> types);
protected:
/// Constructor
/// @param flags the flags of this type
explicit Type(TypeFlags flags);
/// The flags of this type.
const TypeFlags 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.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_

617
src/tint/type/type_test.cc Normal file
View File

@@ -0,0 +1,617 @@
// 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/sem/abstract_float.h"
#include "src/tint/sem/abstract_int.h"
#include "src/tint/sem/f16.h"
#include "src/tint/sem/reference.h"
#include "src/tint/type/array_count.h"
#include "src/tint/type/test_helper.h"
namespace tint::type {
namespace {
struct TypeTest : public TestHelper {
const sem::AbstractFloat* af = create<sem::AbstractFloat>();
const sem::AbstractInt* ai = create<sem::AbstractInt>();
const sem::F32* f32 = create<sem::F32>();
const sem::F16* f16 = create<sem::F16>();
const sem::I32* i32 = create<sem::I32>();
const sem::U32* u32 = create<sem::U32>();
const sem::Vector* vec2_f32 = create<sem::Vector>(f32, 2u);
const sem::Vector* vec3_f32 = create<sem::Vector>(f32, 3u);
const sem::Vector* vec3_f16 = create<sem::Vector>(f16, 3u);
const sem::Vector* vec4_f32 = create<sem::Vector>(f32, 4u);
const sem::Vector* vec3_u32 = create<sem::Vector>(u32, 3u);
const sem::Vector* vec3_i32 = create<sem::Vector>(i32, 3u);
const sem::Vector* vec3_af = create<sem::Vector>(af, 3u);
const sem::Vector* vec3_ai = create<sem::Vector>(ai, 3u);
const sem::Matrix* mat2x4_f32 = create<sem::Matrix>(vec4_f32, 2u);
const sem::Matrix* mat3x4_f32 = create<sem::Matrix>(vec4_f32, 3u);
const sem::Matrix* mat4x2_f32 = create<sem::Matrix>(vec2_f32, 4u);
const sem::Matrix* mat4x3_f32 = create<sem::Matrix>(vec3_f32, 4u);
const sem::Matrix* mat4x3_f16 = create<sem::Matrix>(vec3_f16, 4u);
const sem::Matrix* mat4x3_af = create<sem::Matrix>(vec3_af, 4u);
const sem::Reference* ref_u32 =
create<sem::Reference>(u32, ast::AddressSpace::kPrivate, ast::Access::kReadWrite);
const sem::Struct* str_f32 = create<sem::Struct>(nullptr,
Source{},
Sym("str_f32"),
utils::Vector{
create<sem::StructMember>(
/* declaration */ nullptr,
/* source */ Source{},
/* name */ Sym("x"),
/* type */ f32,
/* index */ 0u,
/* offset */ 0u,
/* align */ 4u,
/* size */ 4u,
/* location */ std::nullopt),
},
/* align*/ 4u,
/* size*/ 4u,
/* size_no_padding*/ 4u);
const sem::Struct* str_f16 = create<sem::Struct>(nullptr,
Source{},
Sym("str_f16"),
utils::Vector{
create<sem::StructMember>(
/* declaration */ nullptr,
/* source */ Source{},
/* name */ Sym("x"),
/* type */ f16,
/* index */ 0u,
/* offset */ 0u,
/* align */ 4u,
/* size */ 4u,
/* location */ std::nullopt),
},
/* align*/ 4u,
/* size*/ 4u,
/* size_no_padding*/ 4u);
sem::Struct* str_af = create<sem::Struct>(nullptr,
Source{},
Sym("str_af"),
utils::Vector{
create<sem::StructMember>(
/* declaration */ nullptr,
/* source */ Source{},
/* name */ Sym("x"),
/* type */ af,
/* index */ 0u,
/* offset */ 0u,
/* align */ 4u,
/* size */ 4u,
/* location */ std::nullopt),
},
/* align*/ 4u,
/* size*/ 4u,
/* size_no_padding*/ 4u);
const sem::Array* arr_i32 = create<sem::Array>(
/* element */ i32,
/* count */ create<type::ConstantArrayCount>(5u),
/* align */ 4u,
/* size */ 5u * 4u,
/* stride */ 5u * 4u,
/* implicit_stride */ 5u * 4u);
const sem::Array* arr_ai = create<sem::Array>(
/* element */ ai,
/* count */ create<type::ConstantArrayCount>(5u),
/* align */ 4u,
/* size */ 5u * 4u,
/* stride */ 5u * 4u,
/* implicit_stride */ 5u * 4u);
const sem::Array* arr_vec3_i32 = create<sem::Array>(
/* element */ vec3_i32,
/* count */ create<ConstantArrayCount>(5u),
/* align */ 16u,
/* size */ 5u * 16u,
/* stride */ 5u * 16u,
/* implicit_stride */ 5u * 16u);
const sem::Array* arr_vec3_ai = create<sem::Array>(
/* element */ vec3_ai,
/* count */ create<type::ConstantArrayCount>(5u),
/* align */ 16u,
/* size */ 5u * 16u,
/* stride */ 5u * 16u,
/* implicit_stride */ 5u * 16u);
const sem::Array* arr_mat4x3_f16 = create<sem::Array>(
/* element */ mat4x3_f16,
/* count */ create<type::ConstantArrayCount>(5u),
/* align */ 32u,
/* size */ 5u * 32u,
/* stride */ 5u * 32u,
/* implicit_stride */ 5u * 32u);
const sem::Array* arr_mat4x3_f32 = create<sem::Array>(
/* element */ mat4x3_f32,
/* count */ create<type::ConstantArrayCount>(5u),
/* align */ 64u,
/* size */ 5u * 64u,
/* stride */ 5u * 64u,
/* implicit_stride */ 5u * 64u);
const sem::Array* arr_mat4x3_af = create<sem::Array>(
/* element */ mat4x3_af,
/* count */ create<type::ConstantArrayCount>(5u),
/* align */ 64u,
/* size */ 5u * 64u,
/* stride */ 5u * 64u,
/* implicit_stride */ 5u * 64u);
const sem::Array* arr_str_f16 = create<sem::Array>(
/* element */ str_f16,
/* count */ create<type::ConstantArrayCount>(5u),
/* align */ 4u,
/* size */ 5u * 4u,
/* stride */ 5u * 4u,
/* implicit_stride */ 5u * 4u);
const sem::Array* arr_str_af = create<sem::Array>(
/* element */ str_af,
/* count */ create<type::ConstantArrayCount>(5u),
/* align */ 4u,
/* size */ 5u * 4u,
/* stride */ 5u * 4u,
/* implicit_stride */ 5u * 4u);
TypeTest() { str_af->SetConcreteTypes(utils::Vector{str_f32, str_f16}); }
};
TEST_F(TypeTest, ConversionRank) {
EXPECT_EQ(Type::ConversionRank(i32, i32), 0u);
EXPECT_EQ(Type::ConversionRank(f32, f32), 0u);
EXPECT_EQ(Type::ConversionRank(u32, u32), 0u);
EXPECT_EQ(Type::ConversionRank(vec3_f32, vec3_f32), 0u);
EXPECT_EQ(Type::ConversionRank(vec3_f16, vec3_f16), 0u);
EXPECT_EQ(Type::ConversionRank(vec4_f32, vec4_f32), 0u);
EXPECT_EQ(Type::ConversionRank(vec3_u32, vec3_u32), 0u);
EXPECT_EQ(Type::ConversionRank(vec3_i32, vec3_i32), 0u);
EXPECT_EQ(Type::ConversionRank(vec3_af, vec3_af), 0u);
EXPECT_EQ(Type::ConversionRank(vec3_ai, vec3_ai), 0u);
EXPECT_EQ(Type::ConversionRank(mat3x4_f32, mat3x4_f32), 0u);
EXPECT_EQ(Type::ConversionRank(mat4x3_f32, mat4x3_f32), 0u);
EXPECT_EQ(Type::ConversionRank(mat4x3_f16, mat4x3_f16), 0u);
EXPECT_EQ(Type::ConversionRank(arr_vec3_ai, arr_vec3_ai), 0u);
EXPECT_EQ(Type::ConversionRank(arr_mat4x3_f16, arr_mat4x3_f16), 0u);
EXPECT_EQ(Type::ConversionRank(mat4x3_af, mat4x3_af), 0u);
EXPECT_EQ(Type::ConversionRank(arr_mat4x3_af, arr_mat4x3_af), 0u);
EXPECT_EQ(Type::ConversionRank(ref_u32, u32), 0u);
EXPECT_EQ(Type::ConversionRank(af, f32), 1u);
EXPECT_EQ(Type::ConversionRank(vec3_af, vec3_f32), 1u);
EXPECT_EQ(Type::ConversionRank(mat4x3_af, mat4x3_f32), 1u);
EXPECT_EQ(Type::ConversionRank(arr_mat4x3_af, arr_mat4x3_f32), 1u);
EXPECT_EQ(Type::ConversionRank(af, f16), 2u);
EXPECT_EQ(Type::ConversionRank(vec3_af, vec3_f16), 2u);
EXPECT_EQ(Type::ConversionRank(mat4x3_af, mat4x3_f16), 2u);
EXPECT_EQ(Type::ConversionRank(arr_mat4x3_af, arr_mat4x3_f16), 2u);
EXPECT_EQ(Type::ConversionRank(ai, i32), 3u);
EXPECT_EQ(Type::ConversionRank(vec3_ai, vec3_i32), 3u);
EXPECT_EQ(Type::ConversionRank(arr_ai, arr_i32), 3u);
EXPECT_EQ(Type::ConversionRank(arr_vec3_ai, arr_vec3_i32), 3u);
EXPECT_EQ(Type::ConversionRank(ai, u32), 4u);
EXPECT_EQ(Type::ConversionRank(vec3_ai, vec3_u32), 4u);
EXPECT_EQ(Type::ConversionRank(ai, af), 5u);
EXPECT_EQ(Type::ConversionRank(ai, f32), 6u);
EXPECT_EQ(Type::ConversionRank(ai, f16), 7u);
EXPECT_EQ(Type::ConversionRank(str_af, str_f32), 1u);
EXPECT_EQ(Type::ConversionRank(str_af, str_f16), 2u);
EXPECT_EQ(Type::ConversionRank(i32, f32), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(f32, u32), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(u32, i32), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(vec3_u32, vec3_f32), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(vec3_f32, vec4_f32), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(mat3x4_f32, mat4x3_f32), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(mat4x3_f32, mat3x4_f32), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(mat4x3_f32, mat4x3_af), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(arr_vec3_i32, arr_vec3_ai), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(arr_mat4x3_f32, arr_mat4x3_af), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(arr_mat4x3_f16, arr_mat4x3_f32), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(f32, af), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(f16, af), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(vec3_f16, vec3_af), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(mat4x3_f16, mat4x3_af), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(i32, af), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(u32, af), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(af, ai), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(f32, ai), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(f16, ai), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(str_f32, str_f16), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(str_f16, str_f32), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(str_f32, str_af), Type::kNoConversion);
EXPECT_EQ(Type::ConversionRank(str_f16, str_af), Type::kNoConversion);
}
TEST_F(TypeTest, ElementOf) {
// No count
EXPECT_TYPE(Type::ElementOf(f32), f32);
EXPECT_TYPE(Type::ElementOf(f16), f16);
EXPECT_TYPE(Type::ElementOf(i32), i32);
EXPECT_TYPE(Type::ElementOf(u32), u32);
EXPECT_TYPE(Type::ElementOf(vec2_f32), f32);
EXPECT_TYPE(Type::ElementOf(vec3_f16), f16);
EXPECT_TYPE(Type::ElementOf(vec4_f32), f32);
EXPECT_TYPE(Type::ElementOf(vec3_u32), u32);
EXPECT_TYPE(Type::ElementOf(vec3_i32), i32);
EXPECT_TYPE(Type::ElementOf(mat2x4_f32), vec4_f32);
EXPECT_TYPE(Type::ElementOf(mat4x2_f32), vec2_f32);
EXPECT_TYPE(Type::ElementOf(mat4x3_f16), vec3_f16);
EXPECT_TYPE(Type::ElementOf(str_f16), str_f16);
EXPECT_TYPE(Type::ElementOf(arr_i32), i32);
EXPECT_TYPE(Type::ElementOf(arr_vec3_i32), vec3_i32);
EXPECT_TYPE(Type::ElementOf(arr_mat4x3_f16), mat4x3_f16);
EXPECT_TYPE(Type::ElementOf(arr_mat4x3_af), mat4x3_af);
EXPECT_TYPE(Type::ElementOf(arr_str_f16), str_f16);
// With count
uint32_t count = 42;
EXPECT_TYPE(Type::ElementOf(f32, &count), f32);
EXPECT_EQ(count, 1u);
count = 42;
EXPECT_TYPE(Type::ElementOf(f16, &count), f16);
EXPECT_EQ(count, 1u);
count = 42;
EXPECT_TYPE(Type::ElementOf(i32, &count), i32);
EXPECT_EQ(count, 1u);
count = 42;
EXPECT_TYPE(Type::ElementOf(u32, &count), u32);
EXPECT_EQ(count, 1u);
count = 42;
EXPECT_TYPE(Type::ElementOf(vec2_f32, &count), f32);
EXPECT_EQ(count, 2u);
count = 42;
EXPECT_TYPE(Type::ElementOf(vec3_f16, &count), f16);
EXPECT_EQ(count, 3u);
count = 42;
EXPECT_TYPE(Type::ElementOf(vec4_f32, &count), f32);
EXPECT_EQ(count, 4u);
count = 42;
EXPECT_TYPE(Type::ElementOf(vec3_u32, &count), u32);
EXPECT_EQ(count, 3u);
count = 42;
EXPECT_TYPE(Type::ElementOf(vec3_i32, &count), i32);
EXPECT_EQ(count, 3u);
count = 42;
EXPECT_TYPE(Type::ElementOf(mat2x4_f32, &count), vec4_f32);
EXPECT_EQ(count, 2u);
count = 42;
EXPECT_TYPE(Type::ElementOf(mat4x2_f32, &count), vec2_f32);
EXPECT_EQ(count, 4u);
count = 42;
EXPECT_TYPE(Type::ElementOf(mat4x3_f16, &count), vec3_f16);
EXPECT_EQ(count, 4u);
count = 42;
EXPECT_TYPE(Type::ElementOf(str_f16, &count), str_f16);
EXPECT_EQ(count, 1u);
count = 42;
EXPECT_TYPE(Type::ElementOf(arr_i32, &count), i32);
EXPECT_EQ(count, 5u);
count = 42;
EXPECT_TYPE(Type::ElementOf(arr_vec3_i32, &count), vec3_i32);
EXPECT_EQ(count, 5u);
count = 42;
EXPECT_TYPE(Type::ElementOf(arr_mat4x3_f16, &count), mat4x3_f16);
EXPECT_EQ(count, 5u);
count = 42;
EXPECT_TYPE(Type::ElementOf(arr_mat4x3_af, &count), mat4x3_af);
EXPECT_EQ(count, 5u);
count = 42;
EXPECT_TYPE(Type::ElementOf(arr_str_f16, &count), str_f16);
EXPECT_EQ(count, 5u);
}
TEST_F(TypeTest, DeepestElementOf) {
// No count
EXPECT_TYPE(Type::DeepestElementOf(f32), f32);
EXPECT_TYPE(Type::DeepestElementOf(f16), f16);
EXPECT_TYPE(Type::DeepestElementOf(i32), i32);
EXPECT_TYPE(Type::DeepestElementOf(u32), u32);
EXPECT_TYPE(Type::DeepestElementOf(vec2_f32), f32);
EXPECT_TYPE(Type::DeepestElementOf(vec3_f16), f16);
EXPECT_TYPE(Type::DeepestElementOf(vec4_f32), f32);
EXPECT_TYPE(Type::DeepestElementOf(vec3_u32), u32);
EXPECT_TYPE(Type::DeepestElementOf(vec3_i32), i32);
EXPECT_TYPE(Type::DeepestElementOf(mat2x4_f32), f32);
EXPECT_TYPE(Type::DeepestElementOf(mat4x2_f32), f32);
EXPECT_TYPE(Type::DeepestElementOf(mat4x3_f16), f16);
EXPECT_TYPE(Type::DeepestElementOf(str_f16), str_f16);
EXPECT_TYPE(Type::DeepestElementOf(arr_i32), i32);
EXPECT_TYPE(Type::DeepestElementOf(arr_vec3_i32), i32);
EXPECT_TYPE(Type::DeepestElementOf(arr_mat4x3_f16), f16);
EXPECT_TYPE(Type::DeepestElementOf(arr_mat4x3_af), af);
EXPECT_TYPE(Type::DeepestElementOf(arr_str_f16), str_f16);
// With count
uint32_t count = 42;
EXPECT_TYPE(Type::DeepestElementOf(f32, &count), f32);
EXPECT_EQ(count, 1u);
count = 42;
EXPECT_TYPE(Type::DeepestElementOf(f16, &count), f16);
EXPECT_EQ(count, 1u);
count = 42;
EXPECT_TYPE(Type::DeepestElementOf(i32, &count), i32);
EXPECT_EQ(count, 1u);
count = 42;
EXPECT_TYPE(Type::DeepestElementOf(u32, &count), u32);
EXPECT_EQ(count, 1u);
count = 42;
EXPECT_TYPE(Type::DeepestElementOf(vec2_f32, &count), f32);
EXPECT_EQ(count, 2u);
count = 42;
EXPECT_TYPE(Type::DeepestElementOf(vec3_f16, &count), f16);
EXPECT_EQ(count, 3u);
count = 42;
EXPECT_TYPE(Type::DeepestElementOf(vec4_f32, &count), f32);
EXPECT_EQ(count, 4u);
count = 42;
EXPECT_TYPE(Type::DeepestElementOf(vec3_u32, &count), u32);
EXPECT_EQ(count, 3u);
count = 42;
EXPECT_TYPE(Type::DeepestElementOf(vec3_i32, &count), i32);
EXPECT_EQ(count, 3u);
count = 42;
EXPECT_TYPE(Type::DeepestElementOf(mat2x4_f32, &count), f32);
EXPECT_EQ(count, 8u);
count = 42;
EXPECT_TYPE(Type::DeepestElementOf(mat4x2_f32, &count), f32);
EXPECT_EQ(count, 8u);
count = 42;
EXPECT_TYPE(Type::DeepestElementOf(mat4x3_f16, &count), f16);
EXPECT_EQ(count, 12u);
count = 42;
EXPECT_TYPE(Type::DeepestElementOf(str_f16, &count), str_f16);
EXPECT_EQ(count, 1u);
count = 42;
EXPECT_TYPE(Type::DeepestElementOf(arr_i32, &count), i32);
EXPECT_EQ(count, 5u);
count = 42;
EXPECT_TYPE(Type::DeepestElementOf(arr_vec3_i32, &count), i32);
EXPECT_EQ(count, 15u);
count = 42;
EXPECT_TYPE(Type::DeepestElementOf(arr_mat4x3_f16, &count), f16);
EXPECT_EQ(count, 60u);
count = 42;
EXPECT_TYPE(Type::DeepestElementOf(arr_mat4x3_af, &count), af);
EXPECT_EQ(count, 60u);
count = 42;
EXPECT_TYPE(Type::DeepestElementOf(arr_str_f16, &count), str_f16);
EXPECT_EQ(count, 5u);
}
TEST_F(TypeTest, Common2) {
EXPECT_TYPE(Type::Common(utils::Vector{ai, ai}), ai);
EXPECT_TYPE(Type::Common(utils::Vector{af, af}), af);
EXPECT_TYPE(Type::Common(utils::Vector{f32, f32}), f32);
EXPECT_TYPE(Type::Common(utils::Vector{f16, f16}), f16);
EXPECT_TYPE(Type::Common(utils::Vector{i32, i32}), i32);
EXPECT_TYPE(Type::Common(utils::Vector{u32, u32}), u32);
EXPECT_TYPE(Type::Common(utils::Vector{i32, u32}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{u32, f32}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{f32, f16}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{f16, i32}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{ai, af}), af);
EXPECT_TYPE(Type::Common(utils::Vector{ai, f32}), f32);
EXPECT_TYPE(Type::Common(utils::Vector{ai, f16}), f16);
EXPECT_TYPE(Type::Common(utils::Vector{ai, i32}), i32);
EXPECT_TYPE(Type::Common(utils::Vector{ai, u32}), u32);
EXPECT_TYPE(Type::Common(utils::Vector{af, ai}), af);
EXPECT_TYPE(Type::Common(utils::Vector{f32, ai}), f32);
EXPECT_TYPE(Type::Common(utils::Vector{f16, ai}), f16);
EXPECT_TYPE(Type::Common(utils::Vector{i32, ai}), i32);
EXPECT_TYPE(Type::Common(utils::Vector{u32, ai}), u32);
EXPECT_TYPE(Type::Common(utils::Vector{ai, af}), af);
EXPECT_TYPE(Type::Common(utils::Vector{f32, af}), f32);
EXPECT_TYPE(Type::Common(utils::Vector{f16, af}), f16);
EXPECT_TYPE(Type::Common(utils::Vector{i32, af}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{u32, af}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{af, ai}), af);
EXPECT_TYPE(Type::Common(utils::Vector{af, f32}), f32);
EXPECT_TYPE(Type::Common(utils::Vector{af, f16}), f16);
EXPECT_TYPE(Type::Common(utils::Vector{af, i32}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{af, u32}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_ai, vec3_ai}), vec3_ai);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_af, vec3_af}), vec3_af);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_f32, vec3_f32}), vec3_f32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_f16, vec3_f16}), vec3_f16);
EXPECT_TYPE(Type::Common(utils::Vector{vec4_f32, vec4_f32}), vec4_f32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_u32, vec3_u32}), vec3_u32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_i32, vec3_i32}), vec3_i32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_ai, vec3_f32}), vec3_f32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_ai, vec3_f16}), vec3_f16);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_ai, vec4_f32}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_ai, vec3_u32}), vec3_u32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_ai, vec3_i32}), vec3_i32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_f32, vec3_ai}), vec3_f32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_f16, vec3_ai}), vec3_f16);
EXPECT_TYPE(Type::Common(utils::Vector{vec4_f32, vec3_ai}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_u32, vec3_ai}), vec3_u32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_i32, vec3_ai}), vec3_i32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_af, vec3_f32}), vec3_f32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_af, vec3_f16}), vec3_f16);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_af, vec4_f32}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_af, vec3_u32}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_af, vec3_i32}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_f32, vec3_af}), vec3_f32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_f16, vec3_af}), vec3_f16);
EXPECT_TYPE(Type::Common(utils::Vector{vec4_f32, vec3_af}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_u32, vec3_af}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_i32, vec3_af}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{mat4x3_af, mat4x3_af}), mat4x3_af);
EXPECT_TYPE(Type::Common(utils::Vector{mat3x4_f32, mat3x4_f32}), mat3x4_f32);
EXPECT_TYPE(Type::Common(utils::Vector{mat4x3_f32, mat4x3_f32}), mat4x3_f32);
EXPECT_TYPE(Type::Common(utils::Vector{mat4x3_f16, mat4x3_f16}), mat4x3_f16);
EXPECT_TYPE(Type::Common(utils::Vector{mat4x3_af, mat3x4_f32}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{mat4x3_af, mat4x3_f32}), mat4x3_f32);
EXPECT_TYPE(Type::Common(utils::Vector{mat4x3_af, mat4x3_f16}), mat4x3_f16);
EXPECT_TYPE(Type::Common(utils::Vector{mat3x4_f32, mat4x3_af}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{mat4x3_f32, mat4x3_af}), mat4x3_f32);
EXPECT_TYPE(Type::Common(utils::Vector{mat4x3_f16, mat4x3_af}), mat4x3_f16);
EXPECT_TYPE(Type::Common(utils::Vector{arr_mat4x3_f32, arr_mat4x3_f16}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{arr_mat4x3_f32, arr_mat4x3_af}), arr_mat4x3_f32);
EXPECT_TYPE(Type::Common(utils::Vector{arr_mat4x3_f16, arr_mat4x3_af}), arr_mat4x3_f16);
}
TEST_F(TypeTest, Common3) {
EXPECT_TYPE(Type::Common(utils::Vector{ai, ai, ai}), ai);
EXPECT_TYPE(Type::Common(utils::Vector{af, af, af}), af);
EXPECT_TYPE(Type::Common(utils::Vector{f32, f32, f32}), f32);
EXPECT_TYPE(Type::Common(utils::Vector{f16, f16, f16}), f16);
EXPECT_TYPE(Type::Common(utils::Vector{i32, i32, i32}), i32);
EXPECT_TYPE(Type::Common(utils::Vector{u32, u32, u32}), u32);
EXPECT_TYPE(Type::Common(utils::Vector{ai, af, ai}), af);
EXPECT_TYPE(Type::Common(utils::Vector{ai, f32, ai}), f32);
EXPECT_TYPE(Type::Common(utils::Vector{ai, f16, ai}), f16);
EXPECT_TYPE(Type::Common(utils::Vector{ai, i32, ai}), i32);
EXPECT_TYPE(Type::Common(utils::Vector{ai, u32, ai}), u32);
EXPECT_TYPE(Type::Common(utils::Vector{af, ai, af}), af);
EXPECT_TYPE(Type::Common(utils::Vector{f32, ai, f32}), f32);
EXPECT_TYPE(Type::Common(utils::Vector{f16, ai, f16}), f16);
EXPECT_TYPE(Type::Common(utils::Vector{i32, ai, i32}), i32);
EXPECT_TYPE(Type::Common(utils::Vector{u32, ai, u32}), u32);
EXPECT_TYPE(Type::Common(utils::Vector{ai, f32, ai}), f32);
EXPECT_TYPE(Type::Common(utils::Vector{ai, f16, ai}), f16);
EXPECT_TYPE(Type::Common(utils::Vector{ai, i32, ai}), i32);
EXPECT_TYPE(Type::Common(utils::Vector{ai, u32, ai}), u32);
EXPECT_TYPE(Type::Common(utils::Vector{f32, ai, f32}), f32);
EXPECT_TYPE(Type::Common(utils::Vector{f16, ai, f16}), f16);
EXPECT_TYPE(Type::Common(utils::Vector{i32, ai, i32}), i32);
EXPECT_TYPE(Type::Common(utils::Vector{u32, ai, u32}), u32);
EXPECT_TYPE(Type::Common(utils::Vector{af, f32, af}), f32);
EXPECT_TYPE(Type::Common(utils::Vector{af, f16, af}), f16);
EXPECT_TYPE(Type::Common(utils::Vector{af, i32, af}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{af, u32, af}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{f32, af, f32}), f32);
EXPECT_TYPE(Type::Common(utils::Vector{f16, af, f16}), f16);
EXPECT_TYPE(Type::Common(utils::Vector{i32, af, i32}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{u32, af, u32}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{ai, af, f32}), f32);
EXPECT_TYPE(Type::Common(utils::Vector{ai, af, f16}), f16);
EXPECT_TYPE(Type::Common(utils::Vector{ai, af, i32}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{ai, af, u32}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_ai, vec3_ai, vec3_ai}), vec3_ai);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_af, vec3_af, vec3_af}), vec3_af);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_f32, vec3_f32, vec3_f32}), vec3_f32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_f16, vec3_f16, vec3_f16}), vec3_f16);
EXPECT_TYPE(Type::Common(utils::Vector{vec4_f32, vec4_f32, vec4_f32}), vec4_f32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_u32, vec3_u32, vec3_u32}), vec3_u32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_i32, vec3_i32, vec3_i32}), vec3_i32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_f32, vec3_ai, vec3_f32}), vec3_f32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_f16, vec3_ai, vec3_f16}), vec3_f16);
EXPECT_TYPE(Type::Common(utils::Vector{vec4_f32, vec3_ai, vec4_f32}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_u32, vec3_ai, vec3_u32}), vec3_u32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_i32, vec3_ai, vec3_i32}), vec3_i32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_ai, vec3_f32, vec3_ai}), vec3_f32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_ai, vec3_f16, vec3_ai}), vec3_f16);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_ai, vec4_f32, vec3_ai}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_ai, vec3_u32, vec3_ai}), vec3_u32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_ai, vec3_i32, vec3_ai}), vec3_i32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_f32, vec3_af, vec3_f32}), vec3_f32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_f16, vec3_af, vec3_f16}), vec3_f16);
EXPECT_TYPE(Type::Common(utils::Vector{vec4_f32, vec3_af, vec4_f32}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_u32, vec3_af, vec3_u32}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_i32, vec3_af, vec3_i32}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_af, vec3_f32, vec3_af}), vec3_f32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_af, vec3_f16, vec3_af}), vec3_f16);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_af, vec4_f32, vec3_af}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_af, vec3_u32, vec3_af}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_af, vec3_i32, vec3_af}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_ai, vec3_af, vec3_f32}), vec3_f32);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_ai, vec3_af, vec3_f16}), vec3_f16);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_ai, vec3_af, vec4_f32}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_ai, vec3_af, vec3_u32}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{vec3_ai, vec3_af, vec3_i32}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{mat4x3_af, mat4x3_af, mat4x3_af}), mat4x3_af);
EXPECT_TYPE(Type::Common(utils::Vector{mat3x4_f32, mat3x4_f32, mat3x4_f32}), mat3x4_f32);
EXPECT_TYPE(Type::Common(utils::Vector{mat4x3_f32, mat4x3_f32, mat4x3_f32}), mat4x3_f32);
EXPECT_TYPE(Type::Common(utils::Vector{mat4x3_f16, mat4x3_f16, mat4x3_f16}), mat4x3_f16);
EXPECT_TYPE(Type::Common(utils::Vector{mat3x4_f32, mat4x3_af, mat3x4_f32}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{mat4x3_f32, mat4x3_af, mat4x3_f32}), mat4x3_f32);
EXPECT_TYPE(Type::Common(utils::Vector{mat4x3_f16, mat4x3_af, mat4x3_f16}), mat4x3_f16);
EXPECT_TYPE(Type::Common(utils::Vector{mat4x3_af, mat3x4_f32, mat4x3_af}), nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{mat4x3_af, mat4x3_f32, mat4x3_af}), mat4x3_f32);
EXPECT_TYPE(Type::Common(utils::Vector{mat4x3_af, mat4x3_f16, mat4x3_af}), mat4x3_f16);
EXPECT_TYPE(Type::Common(utils::Vector{arr_mat4x3_f16, arr_mat4x3_f32, arr_mat4x3_f16}),
nullptr);
EXPECT_TYPE(Type::Common(utils::Vector{arr_mat4x3_af, arr_mat4x3_f32, arr_mat4x3_af}),
arr_mat4x3_f32);
EXPECT_TYPE(Type::Common(utils::Vector{arr_mat4x3_af, arr_mat4x3_f16, arr_mat4x3_af}),
arr_mat4x3_f16);
}
TEST_F(TypeTest, HoldsAbstract) {
EXPECT_TRUE(af->HoldsAbstract());
EXPECT_TRUE(ai->HoldsAbstract());
EXPECT_FALSE(f32->HoldsAbstract());
EXPECT_FALSE(f16->HoldsAbstract());
EXPECT_FALSE(i32->HoldsAbstract());
EXPECT_FALSE(u32->HoldsAbstract());
EXPECT_FALSE(vec2_f32->HoldsAbstract());
EXPECT_FALSE(vec3_f32->HoldsAbstract());
EXPECT_FALSE(vec3_f16->HoldsAbstract());
EXPECT_FALSE(vec4_f32->HoldsAbstract());
EXPECT_FALSE(vec3_u32->HoldsAbstract());
EXPECT_FALSE(vec3_i32->HoldsAbstract());
EXPECT_TRUE(vec3_af->HoldsAbstract());
EXPECT_TRUE(vec3_ai->HoldsAbstract());
EXPECT_FALSE(mat2x4_f32->HoldsAbstract());
EXPECT_FALSE(mat3x4_f32->HoldsAbstract());
EXPECT_FALSE(mat4x2_f32->HoldsAbstract());
EXPECT_FALSE(mat4x3_f32->HoldsAbstract());
EXPECT_FALSE(mat4x3_f16->HoldsAbstract());
EXPECT_TRUE(mat4x3_af->HoldsAbstract());
EXPECT_FALSE(str_f16->HoldsAbstract());
EXPECT_TRUE(str_af->HoldsAbstract());
EXPECT_FALSE(arr_i32->HoldsAbstract());
EXPECT_TRUE(arr_ai->HoldsAbstract());
EXPECT_FALSE(arr_vec3_i32->HoldsAbstract());
EXPECT_TRUE(arr_vec3_ai->HoldsAbstract());
EXPECT_FALSE(arr_mat4x3_f16->HoldsAbstract());
EXPECT_FALSE(arr_mat4x3_f32->HoldsAbstract());
EXPECT_TRUE(arr_mat4x3_af->HoldsAbstract());
EXPECT_FALSE(arr_str_f16->HoldsAbstract());
EXPECT_TRUE(arr_str_af->HoldsAbstract());
}
} // namespace
} // namespace tint::type