tint/resolver: Add tests for implicit type materialization
These are tests for when there's no explicit target type for a
materialization. In this case we expect an abstract-int to
materialize to an i32 and an abstract-float to materialize to a
f32.
Fix a bug uncovered where we were creating a transposed matrix.
Bug: tint:1504
Change-Id: Ie69dd7ec47174d3d7bef20315fd3780dade3a325
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/91845
Reviewed-by: David Neto <dneto@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/resolver/materialize_test.cc b/src/tint/resolver/materialize_test.cc
index 6573426..2bd74cc 100644
--- a/src/tint/resolver/materialize_test.cc
+++ b/src/tint/resolver/materialize_test.cc
@@ -34,10 +34,44 @@
using u32V = builder::vec<3, u32>;
using f32M = builder::mat<3, 2, f32>;
-////////////////////////////////////////////////////////////////////////////////
-// MaterializeTests
-////////////////////////////////////////////////////////////////////////////////
-namespace MaterializeTests {
+constexpr double kHighestU32 = static_cast<double>(u32::kHighest);
+constexpr double kLowestU32 = static_cast<double>(u32::kLowest);
+constexpr double kHighestI32 = static_cast<double>(i32::kHighest);
+constexpr double kLowestI32 = static_cast<double>(i32::kLowest);
+constexpr double kHighestF32 = static_cast<double>(f32::kHighest);
+constexpr double kLowestF32 = static_cast<double>(f32::kLowest);
+constexpr double kTooBigF32 = static_cast<double>(3.5e+38);
+constexpr double kPiF64 = 3.141592653589793;
+constexpr double kPiF32 = 3.1415927410125732; // kPiF64 quantized to f32
+
+constexpr double kSubnormalF32 = 0x1.0p-128;
+
+enum class Expectation {
+ kMaterialize,
+ kNoMaterialize,
+ kInvalidConversion,
+ kValueCannotBeRepresented,
+};
+
+static std::ostream& operator<<(std::ostream& o, Expectation m) {
+ switch (m) {
+ case Expectation::kMaterialize:
+ return o << "materialize";
+ case Expectation::kNoMaterialize:
+ return o << "no-materialize";
+ case Expectation::kInvalidConversion:
+ return o << "invalid-conversion";
+ case Expectation::kValueCannotBeRepresented:
+ return o << "value cannot be represented";
+ }
+ return o << "<unknown>";
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// MaterializeAbstractNumericToConcreteType
+// Tests that an abstract-numeric will materialize to the expected concrete type
+////////////////////////////////////////////////////////////////////////////////////////////////////
+namespace materialize_abstract_numeric_to_concrete_type {
// How should the materialization occur?
enum class Method {
@@ -188,31 +222,10 @@
return o;
}
-enum class Expectation {
- kMaterialize,
- kNoMaterialize,
- kInvalidCast,
- kValueCannotBeRepresented,
-};
-
-static std::ostream& operator<<(std::ostream& o, Expectation m) {
- switch (m) {
- case Expectation::kMaterialize:
- return o << "pass";
- case Expectation::kNoMaterialize:
- return o << "no-materialize";
- case Expectation::kInvalidCast:
- return o << "invalid-cast";
- case Expectation::kValueCannotBeRepresented:
- return o << "value too low or high";
- }
- return o << "<unknown>";
-}
-
-using MaterializeAbstractNumeric =
+using MaterializeAbstractNumericToConcreteType =
resolver::ResolverTestWithParam<std::tuple<Expectation, Method, Data>>;
-TEST_P(MaterializeAbstractNumeric, Test) {
+TEST_P(MaterializeAbstractNumericToConcreteType, Test) {
// Once F16 is properly supported, we'll need to enable this:
// Enable(ast::Extension::kF16);
@@ -309,7 +322,7 @@
check_types_and_values(sem);
break;
}
- case Expectation::kInvalidCast: {
+ case Expectation::kInvalidConversion: {
ASSERT_FALSE(r()->Resolve());
std::string expect;
switch (method) {
@@ -338,170 +351,484 @@
}
/// Methods that support scalar materialization
-constexpr Method kScalarMethods[] = {Method::kLet, //
- Method::kVar, //
- Method::kFnArg, //
- Method::kBuiltinArg, //
- Method::kReturn, //
- Method::kArray, //
- Method::kStruct, //
- Method::kBinaryOp};
+constexpr Method kScalarMethods[] = {
+ Method::kLet, Method::kVar, Method::kFnArg, Method::kBuiltinArg,
+ Method::kReturn, Method::kArray, Method::kStruct, Method::kBinaryOp,
+};
/// Methods that support vector materialization
-constexpr Method kVectorMethods[] = {Method::kLet, //
- Method::kVar, //
- Method::kFnArg, //
- Method::kBuiltinArg, //
- Method::kReturn, //
- Method::kArray, //
- Method::kStruct, //
- Method::kBinaryOp};
+constexpr Method kVectorMethods[] = {
+ Method::kLet, Method::kVar, Method::kFnArg, Method::kBuiltinArg,
+ Method::kReturn, Method::kArray, Method::kStruct, Method::kBinaryOp,
+};
/// Methods that support matrix materialization
-constexpr Method kMatrixMethods[] = {Method::kLet, //
- Method::kVar, //
- Method::kFnArg, //
- Method::kReturn, //
- Method::kArray, //
- Method::kStruct, //
- Method::kBinaryOp};
+constexpr Method kMatrixMethods[] = {
+ Method::kLet, Method::kVar, Method::kFnArg, Method::kReturn,
+ Method::kArray, Method::kStruct, Method::kBinaryOp,
+};
/// Methods that support materialization for switch cases
-constexpr Method kSwitchMethods[] = {Method::kSwitchCond, //
- Method::kSwitchCase, //
- Method::kSwitchCondWithAbstractCase, //
- Method::kSwitchCaseWithAbstractCase};
-
-constexpr double kMaxF32 = static_cast<double>(f32::kHighest);
-constexpr double kPiF64 = 3.141592653589793;
-constexpr double kPiF32 = 3.1415927410125732; // kPiF64 quantized to f32
-
-constexpr double kSubnormalF32 = 0x1.0p-128;
+constexpr Method kSwitchMethods[] = {
+ Method::kSwitchCond,
+ Method::kSwitchCase,
+ Method::kSwitchCondWithAbstractCase,
+ Method::kSwitchCaseWithAbstractCase,
+};
INSTANTIATE_TEST_SUITE_P(
MaterializeScalar,
- MaterializeAbstractNumeric, //
- testing::Combine(testing::Values(Expectation::kMaterialize), //
- testing::ValuesIn(kScalarMethods), //
- testing::Values(Types<i32, AInt>(0_a, 0.0), //
- Types<i32, AInt>(2147483647_a, 2147483647.0), //
- Types<i32, AInt>(-2147483648_a, -2147483648.0), //
- Types<u32, AInt>(0_a, 0.0), //
- Types<u32, AInt>(4294967295_a, 4294967295.0), //
- Types<f32, AFloat>(0.0_a, 0.0), //
- Types<f32, AFloat>(AFloat(kMaxF32), kMaxF32), //
- Types<f32, AFloat>(AFloat(-kMaxF32), -kMaxF32), //
- Types<f32, AFloat>(AFloat(kPiF32), kPiF64), //
- Types<f32, AFloat>(AFloat(kSubnormalF32), kSubnormalF32), //
- Types<f32, AFloat>(AFloat(-kSubnormalF32), -kSubnormalF32) //
- /* Types<f16, AFloat>(1.0_a), */ //
- /* Types<f16, AFloat>(1.0_a), */)));
+ MaterializeAbstractNumericToConcreteType,
+ testing::Combine(testing::Values(Expectation::kMaterialize),
+ testing::ValuesIn(kScalarMethods),
+ testing::ValuesIn(std::vector<Data>{
+ Types<i32, AInt>(0_a, 0.0), //
+ Types<i32, AInt>(1_a, 1.0), //
+ Types<i32, AInt>(-1_a, -1.0), //
+ Types<i32, AInt>(AInt(kHighestI32), kHighestI32), //
+ Types<i32, AInt>(AInt(kLowestI32), kLowestI32), //
+ Types<u32, AInt>(0_a, 0.0), //
+ Types<u32, AInt>(1_a, 1.0), //
+ Types<u32, AInt>(AInt(kHighestU32), kHighestU32), //
+ Types<u32, AInt>(AInt(kLowestU32), kLowestU32), //
+ Types<f32, AFloat>(0.0_a, 0.0), //
+ Types<f32, AFloat>(AFloat(kHighestF32), kHighestF32), //
+ Types<f32, AFloat>(AFloat(kLowestF32), kLowestF32), //
+ Types<f32, AFloat>(AFloat(kPiF32), kPiF64), //
+ Types<f32, AFloat>(AFloat(kSubnormalF32), kSubnormalF32), //
+ Types<f32, AFloat>(AFloat(-kSubnormalF32), -kSubnormalF32), //
+ /* Types<f16, AFloat>(1.0_a), */ //
+ /* Types<f16, AFloat>(1.0_a), */ //
+ })));
INSTANTIATE_TEST_SUITE_P(
MaterializeVector,
- MaterializeAbstractNumeric, //
- testing::Combine(testing::Values(Expectation::kMaterialize), //
- testing::ValuesIn(kVectorMethods), //
- testing::Values(Types<i32V, AIntV>(0_a, 0.0), //
- Types<i32V, AIntV>(2147483647_a, 2147483647.0), //
- Types<i32V, AIntV>(-2147483648_a, -2147483648.0), //
- Types<u32V, AIntV>(0_a, 0.0), //
- Types<u32V, AIntV>(4294967295_a, 4294967295.0), //
- Types<f32V, AFloatV>(0.0_a, 0.0), //
- Types<f32V, AFloatV>(AFloat(kMaxF32), kMaxF32), //
- Types<f32V, AFloatV>(AFloat(-kMaxF32), -kMaxF32), //
- Types<f32V, AFloatV>(AFloat(kPiF32), kPiF64), //
- Types<f32V, AFloatV>(AFloat(kSubnormalF32), kSubnormalF32), //
- Types<f32V, AFloatV>(AFloat(-kSubnormalF32),
- -kSubnormalF32) //
- /* Types<f16V, AFloatV>(1.0_a), */ //
- /* Types<f16V, AFloatV>(1.0_a), */)));
+ MaterializeAbstractNumericToConcreteType,
+ testing::Combine(testing::Values(Expectation::kMaterialize),
+ testing::ValuesIn(kVectorMethods),
+ testing::ValuesIn(std::vector<Data>{
+ Types<i32V, AIntV>(0_a, 0.0), //
+ Types<i32V, AIntV>(1_a, 1.0), //
+ Types<i32V, AIntV>(-1_a, -1.0), //
+ Types<i32V, AIntV>(AInt(kHighestI32), kHighestI32), //
+ Types<i32V, AIntV>(AInt(kLowestI32), kLowestI32), //
+ Types<u32V, AIntV>(0_a, 0.0), //
+ Types<u32V, AIntV>(1_a, 1.0), //
+ Types<u32V, AIntV>(AInt(kHighestU32), kHighestU32), //
+ Types<u32V, AIntV>(AInt(kLowestU32), kLowestU32), //
+ Types<f32V, AFloatV>(0.0_a, 0.0), //
+ Types<f32V, AFloatV>(1.0_a, 1.0), //
+ Types<f32V, AFloatV>(-1.0_a, -1.0), //
+ Types<f32V, AFloatV>(AFloat(kHighestF32), kHighestF32), //
+ Types<f32V, AFloatV>(AFloat(kLowestF32), kLowestF32), //
+ Types<f32V, AFloatV>(AFloat(kPiF32), kPiF64), //
+ Types<f32V, AFloatV>(AFloat(kSubnormalF32), kSubnormalF32), //
+ Types<f32V, AFloatV>(AFloat(-kSubnormalF32), -kSubnormalF32), //
+ /* Types<f16V, AFloatV>(1.0_a), */ //
+ /* Types<f16V, AFloatV>(1.0_a), */ //
+ })));
INSTANTIATE_TEST_SUITE_P(
MaterializeMatrix,
- MaterializeAbstractNumeric, //
- testing::Combine(testing::Values(Expectation::kMaterialize), //
- testing::ValuesIn(kMatrixMethods), //
- testing::Values(Types<f32M, AFloatM>(0.0_a, 0.0), //
- Types<f32M, AFloatM>(AFloat(kMaxF32), kMaxF32), //
- Types<f32M, AFloatM>(AFloat(-kMaxF32), -kMaxF32), //
- Types<f32M, AFloatM>(AFloat(kPiF32), kPiF64), //
- Types<f32M, AFloatM>(AFloat(kSubnormalF32), kSubnormalF32), //
- Types<f32M, AFloatM>(AFloat(-kSubnormalF32),
- -kSubnormalF32) //
- /* Types<f16V, AFloatM>(1.0_a), */ //
- )));
+ MaterializeAbstractNumericToConcreteType,
+ testing::Combine(testing::Values(Expectation::kMaterialize),
+ testing::ValuesIn(kMatrixMethods),
+ testing::ValuesIn(std::vector<Data>{
+ Types<f32M, AFloatM>(0.0_a, 0.0), //
+ Types<f32M, AFloatM>(1.0_a, 1.0), //
+ Types<f32M, AFloatM>(-1.0_a, -1.0), //
+ Types<f32M, AFloatM>(AFloat(kHighestF32), kHighestF32), //
+ Types<f32M, AFloatM>(AFloat(kLowestF32), kLowestF32), //
+ Types<f32M, AFloatM>(AFloat(kPiF32), kPiF64), //
+ Types<f32M, AFloatM>(AFloat(kSubnormalF32), kSubnormalF32), //
+ Types<f32M, AFloatM>(AFloat(-kSubnormalF32), -kSubnormalF32), //
+ /* Types<f16V, AFloatM>(1.0_a), */ //
+ })));
-INSTANTIATE_TEST_SUITE_P(
- MaterializeSwitch,
- MaterializeAbstractNumeric, //
- testing::Combine(testing::Values(Expectation::kMaterialize), //
- testing::ValuesIn(kSwitchMethods), //
- testing::Values(Types<i32, AInt>(0_a, 0.0), //
- Types<i32, AInt>(2147483647_a, 2147483647.0), //
- Types<i32, AInt>(-2147483648_a, -2147483648.0), //
- Types<u32, AInt>(0_a, 0.0), //
- Types<u32, AInt>(4294967295_a, 4294967295.0))));
+INSTANTIATE_TEST_SUITE_P(MaterializeSwitch,
+ MaterializeAbstractNumericToConcreteType,
+ testing::Combine(testing::Values(Expectation::kMaterialize),
+ testing::ValuesIn(kSwitchMethods),
+ testing::ValuesIn(std::vector<Data>{
+ Types<i32, AInt>(0_a, 0.0), //
+ Types<i32, AInt>(1_a, 1.0), //
+ Types<i32, AInt>(-1_a, -1.0), //
+ Types<i32, AInt>(AInt(kHighestI32), kHighestI32), //
+ Types<i32, AInt>(AInt(kLowestI32), kLowestI32), //
+ Types<u32, AInt>(0_a, 0.0), //
+ Types<u32, AInt>(1_a, 1.0), //
+ Types<u32, AInt>(AInt(kHighestU32), kHighestU32), //
+ Types<u32, AInt>(AInt(kLowestU32), kLowestU32), //
+ })));
// TODO(crbug.com/tint/1504): Enable once we have abstract overloads of builtins / binary ops.
INSTANTIATE_TEST_SUITE_P(DISABLED_NoMaterialize,
- MaterializeAbstractNumeric, //
- testing::Combine(testing::Values(Expectation::kNoMaterialize), //
- testing::Values(Method::kBuiltinArg, //
- Method::kBinaryOp), //
- testing::Values(Types<AInt, AInt>(), //
- Types<AFloat, AFloat>(), //
- Types<AIntV, AIntV>(), //
- Types<AFloatV, AFloatV>(), //
- Types<AFloatM, AFloatM>())));
-INSTANTIATE_TEST_SUITE_P(InvalidCast,
- MaterializeAbstractNumeric, //
- testing::Combine(testing::Values(Expectation::kInvalidCast), //
- testing::ValuesIn(kScalarMethods), //
- testing::Values(Types<i32, AFloat>(), //
- Types<u32, AFloat>(), //
- Types<i32V, AFloatV>(), //
- Types<u32V, AFloatV>())));
+ MaterializeAbstractNumericToConcreteType,
+ testing::Combine(testing::Values(Expectation::kNoMaterialize),
+ testing::Values(Method::kBuiltinArg, Method::kBinaryOp),
+ testing::ValuesIn(std::vector<Data>{
+ Types<AInt, AInt>(), //
+ Types<AFloat, AFloat>(), //
+ Types<AIntV, AIntV>(), //
+ Types<AFloatV, AFloatV>(), //
+ Types<AFloatM, AFloatM>(), //
+ })));
+INSTANTIATE_TEST_SUITE_P(InvalidConversion,
+ MaterializeAbstractNumericToConcreteType,
+ testing::Combine(testing::Values(Expectation::kInvalidConversion),
+ testing::ValuesIn(kScalarMethods),
+ testing::ValuesIn(std::vector<Data>{
+ Types<i32, AFloat>(), //
+ Types<u32, AFloat>(), //
+ Types<i32V, AFloatV>(), //
+ Types<u32V, AFloatV>(), //
+ })));
+
+INSTANTIATE_TEST_SUITE_P(ScalarValueCannotBeRepresented,
+ MaterializeAbstractNumericToConcreteType,
+ testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented),
+ testing::ValuesIn(kScalarMethods),
+ testing::ValuesIn(std::vector<Data>{
+ Types<i32, AInt>(0_a, kHighestI32 + 1), //
+ Types<i32, AInt>(0_a, kLowestI32 - 1), //
+ Types<u32, AInt>(0_a, kHighestU32 + 1), //
+ Types<u32, AInt>(0_a, kLowestU32 - 1), //
+ Types<f32, AFloat>(0.0_a, kTooBigF32), //
+ Types<f32, AFloat>(0.0_a, -kTooBigF32), //
+ /* Types<f16, AFloat>(), */ //
+ /* Types<f16, AFloat>(), */ //
+ })));
+
+INSTANTIATE_TEST_SUITE_P(VectorValueCannotBeRepresented,
+ MaterializeAbstractNumericToConcreteType,
+ testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented),
+ testing::ValuesIn(kVectorMethods),
+ testing::ValuesIn(std::vector<Data>{
+ Types<i32V, AIntV>(0_a, kHighestI32 + 1), //
+ Types<i32V, AIntV>(0_a, kLowestI32 - 1), //
+ Types<u32V, AIntV>(0_a, kHighestU32 + 1), //
+ Types<u32V, AIntV>(0_a, kLowestU32 - 1), //
+ Types<f32V, AFloatV>(0.0_a, kTooBigF32), //
+ Types<f32V, AFloatV>(0.0_a, -kTooBigF32), //
+ /* Types<f16V, AFloatV>(), */ //
+ /* Types<f16V, AFloatV>(), */ //
+ })));
+
+INSTANTIATE_TEST_SUITE_P(MatrixValueCannotBeRepresented,
+ MaterializeAbstractNumericToConcreteType,
+ testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented),
+ testing::ValuesIn(kMatrixMethods),
+ testing::ValuesIn(std::vector<Data>{
+ Types<f32M, AFloatM>(0.0_a, kTooBigF32), //
+ Types<f32M, AFloatM>(0.0_a, -kTooBigF32), //
+ /* Types<f16M, AFloatM>(), */ //
+ /* Types<f16M, AFloatM>(), */ //
+ })));
+
+} // namespace materialize_abstract_numeric_to_concrete_type
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Tests that in the absence of a 'target type' an abstract-int will materialize to i32, and an
+// abstract-float will materialize to f32.
+////////////////////////////////////////////////////////////////////////////////////////////////////
+namespace materialize_abstract_numeric_to_default_type {
+
+// How should the materialization occur?
+enum class Method {
+ // var a = abstract_expr;
+ kVar,
+
+ // let a = abstract_expr;
+ kLet,
+
+ // min(abstract_expr, abstract_expr);
+ kBuiltinArg,
+
+ // array<i32, abstract_expr>();
+ kArrayLength,
+
+ // switch (abstract_expr) {
+ // case abstract_expr: {}
+ // default: {}
+ // }
+ kSwitch,
+};
+
+static std::ostream& operator<<(std::ostream& o, Method m) {
+ switch (m) {
+ case Method::kVar:
+ return o << "var";
+ case Method::kLet:
+ return o << "let";
+ case Method::kBuiltinArg:
+ return o << "builtin-arg";
+ case Method::kArrayLength:
+ return o << "array-length";
+ case Method::kSwitch:
+ return o << "switch";
+ }
+ return o << "<unknown>";
+}
+
+struct Data {
+ std::string expected_type_name;
+ std::string expected_element_type_name;
+ builder::sem_type_func_ptr expected_sem_ty;
+ std::string abstract_type_name;
+ builder::ast_expr_func_ptr abstract_expr;
+ std::variant<AInt, AFloat> materialized_value;
+ double literal_value;
+};
+
+template <typename EXPECTED_TYPE, typename ABSTRACT_TYPE, typename MATERIALIZED_TYPE>
+Data Types(MATERIALIZED_TYPE materialized_value, double literal_value) {
+ using ExpectedDataType = builder::DataType<EXPECTED_TYPE>;
+ using AbstractDataType = builder::DataType<ABSTRACT_TYPE>;
+ using TargetElementDataType = builder::DataType<typename ExpectedDataType::ElementType>;
+ return {
+ ExpectedDataType::Name(), // expected_type_name
+ TargetElementDataType::Name(), // expected_element_type_name
+ ExpectedDataType::Sem, // expected_sem_ty
+ AbstractDataType::Name(), // abstract_type_name
+ AbstractDataType::Expr, // abstract_expr
+ materialized_value,
+ literal_value,
+ };
+}
+
+static std::ostream& operator<<(std::ostream& o, const Data& c) {
+ auto print_value = [&](auto&& v) { o << v; };
+ o << "[" << c.expected_type_name << " <- " << c.abstract_type_name << "] [";
+ std::visit(print_value, c.materialized_value);
+ o << " <- " << c.literal_value << "]";
+ return o;
+}
+
+using MaterializeAbstractNumericToDefaultType =
+ resolver::ResolverTestWithParam<std::tuple<Expectation, Method, Data>>;
+
+TEST_P(MaterializeAbstractNumericToDefaultType, Test) {
+ // Once F16 is properly supported, we'll need to enable this:
+ // Enable(ast::Extension::kF16);
+
+ const auto& param = GetParam();
+ const auto& expectation = std::get<0>(param);
+ const auto& method = std::get<1>(param);
+ const auto& data = std::get<2>(param);
+
+ ast::ExpressionList abstract_exprs;
+ auto abstract_expr = [&] {
+ auto* expr = data.abstract_expr(*this, data.literal_value);
+ abstract_exprs.emplace_back(expr);
+ return expr;
+ };
+ switch (method) {
+ case Method::kVar:
+ WrapInFunction(Decl(Var("a", nullptr, abstract_expr())));
+ break;
+ case Method::kLet:
+ WrapInFunction(Decl(Let("a", nullptr, abstract_expr())));
+ break;
+ case Method::kBuiltinArg:
+ WrapInFunction(CallStmt(Call("min", abstract_expr(), abstract_expr())));
+ break;
+ case Method::kArrayLength:
+ WrapInFunction(Construct(ty.array(ty.i32(), abstract_expr())));
+ break;
+ case Method::kSwitch:
+ WrapInFunction(Switch(abstract_expr(),
+ Case(abstract_expr()->As<ast::IntLiteralExpression>()),
+ DefaultCase()));
+ break;
+ }
+
+ auto check_types_and_values = [&](const sem::Expression* expr) {
+ auto* expected_sem_ty = data.expected_sem_ty(*this);
+
+ EXPECT_TYPE(expr->Type(), expected_sem_ty);
+ EXPECT_TYPE(expr->ConstantValue().Type(), expected_sem_ty);
+
+ uint32_t num_elems = 0;
+ const sem::Type* expected_sem_el_ty = sem::Type::ElementOf(expected_sem_ty, &num_elems);
+ EXPECT_TYPE(expr->ConstantValue().ElementType(), expected_sem_el_ty);
+ expr->ConstantValue().WithElements([&](auto&& vec) {
+ using VEC_TY = std::decay_t<decltype(vec)>;
+ using EL_TY = typename VEC_TY::value_type;
+ ASSERT_TRUE(std::holds_alternative<EL_TY>(data.materialized_value));
+ VEC_TY expected(num_elems, std::get<EL_TY>(data.materialized_value));
+ EXPECT_EQ(vec, expected);
+ });
+ };
+
+ switch (expectation) {
+ case Expectation::kMaterialize: {
+ ASSERT_TRUE(r()->Resolve()) << r()->error();
+ for (auto* expr : abstract_exprs) {
+ auto* materialize = Sem().Get<sem::Materialize>(expr);
+ ASSERT_NE(materialize, nullptr);
+ check_types_and_values(materialize);
+ }
+ break;
+ }
+ case Expectation::kInvalidConversion: {
+ ASSERT_FALSE(r()->Resolve());
+ std::string expect;
+ switch (method) {
+ case Method::kBuiltinArg:
+ expect = "error: no matching call to min(" + data.abstract_type_name + ", " +
+ data.abstract_type_name + ")";
+ break;
+ default:
+ expect = "error: cannot convert value of type '" + data.abstract_type_name +
+ "' to type '" + data.expected_type_name + "'";
+ break;
+ }
+ EXPECT_THAT(r()->error(), testing::StartsWith(expect));
+ break;
+ }
+ case Expectation::kValueCannotBeRepresented:
+ ASSERT_FALSE(r()->Resolve());
+ EXPECT_THAT(r()->error(), testing::HasSubstr("cannot be represented as '" +
+ data.expected_element_type_name + "'"));
+ break;
+ default:
+ FAIL() << "unhandled expectation: " << expectation;
+ }
+}
+
+/// Methods that support scalar materialization
+constexpr Method kScalarMethods[] = {
+ Method::kLet,
+ Method::kVar,
+ Method::kBuiltinArg,
+};
+
+/// Methods that support vector materialization
+constexpr Method kVectorMethods[] = {
+ Method::kLet,
+ Method::kVar,
+ Method::kBuiltinArg,
+};
+
+/// Methods that support matrix materialization
+constexpr Method kMatrixMethods[] = {
+ Method::kLet,
+ Method::kVar,
+};
+
+/// Methods that support materialization for switch cases
+constexpr Method kSwitchMethods[] = {
+ Method::kSwitch,
+};
INSTANTIATE_TEST_SUITE_P(
- ScalarValueCannotBeRepresented,
- MaterializeAbstractNumeric, //
- testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented), //
- testing::ValuesIn(kScalarMethods), //
- testing::Values(Types<i32, AInt>(0_a, 2147483648.0), //
- Types<i32, AInt>(0_a, -2147483649.0), //
- Types<u32, AInt>(0_a, 4294967296), //
- Types<u32, AInt>(0_a, -1.0), //
- Types<f32, AFloat>(0.0_a, 3.5e+38), //
- Types<f32, AFloat>(0.0_a, -3.5e+38) //
- /* Types<f16, AFloat>(), */ //
- /* Types<f16, AFloat>(), */)));
+ MaterializeScalar,
+ MaterializeAbstractNumericToDefaultType,
+ testing::Combine(testing::Values(Expectation::kMaterialize),
+ testing::ValuesIn(kScalarMethods),
+ testing::ValuesIn(std::vector<Data>{
+ Types<i32, AInt>(0_a, 0.0), //
+ Types<i32, AInt>(1_a, 1.0), //
+ Types<i32, AInt>(-1_a, -1.0), //
+ Types<i32, AInt>(AInt(kHighestI32), kHighestI32), //
+ Types<i32, AInt>(AInt(kLowestI32), kLowestI32), //
+ Types<f32, AFloat>(0.0_a, 0.0), //
+ Types<f32, AFloat>(AFloat(kHighestF32), kHighestF32), //
+ Types<f32, AFloat>(AFloat(kLowestF32), kLowestF32), //
+ Types<f32, AFloat>(AFloat(kPiF32), kPiF64), //
+ Types<f32, AFloat>(AFloat(kSubnormalF32), kSubnormalF32), //
+ Types<f32, AFloat>(AFloat(-kSubnormalF32), -kSubnormalF32), //
+ })));
INSTANTIATE_TEST_SUITE_P(
- VectorValueCannotBeRepresented,
- MaterializeAbstractNumeric, //
- testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented), //
- testing::ValuesIn(kVectorMethods), //
- testing::Values(Types<i32V, AIntV>(0_a, 2147483648.0), //
- Types<i32V, AIntV>(0_a, -2147483649.0), //
- Types<u32V, AIntV>(0_a, 4294967296), //
- Types<u32V, AIntV>(0_a, -1.0), //
- Types<f32V, AFloatV>(0.0_a, 3.5e+38), //
- Types<f32V, AFloatV>(0.0_a, -3.5e+38) //
- /* Types<f16V, AFloatV>(), */ //
- /* Types<f16V, AFloatV>(), */)));
+ MaterializeVector,
+ MaterializeAbstractNumericToDefaultType,
+ testing::Combine(testing::Values(Expectation::kMaterialize),
+ testing::ValuesIn(kVectorMethods),
+ testing::ValuesIn(std::vector<Data>{
+ Types<i32V, AIntV>(0_a, 0.0), //
+ Types<i32V, AIntV>(1_a, 1.0), //
+ Types<i32V, AIntV>(-1_a, -1.0), //
+ Types<i32V, AIntV>(AInt(kHighestI32), kHighestI32), //
+ Types<i32V, AIntV>(AInt(kLowestI32), kLowestI32), //
+ Types<f32V, AFloatV>(0.0_a, 0.0), //
+ Types<f32V, AFloatV>(1.0_a, 1.0), //
+ Types<f32V, AFloatV>(-1.0_a, -1.0), //
+ Types<f32V, AFloatV>(AFloat(kHighestF32), kHighestF32), //
+ Types<f32V, AFloatV>(AFloat(kLowestF32), kLowestF32), //
+ Types<f32V, AFloatV>(AFloat(kPiF32), kPiF64), //
+ Types<f32V, AFloatV>(AFloat(kSubnormalF32), kSubnormalF32), //
+ Types<f32V, AFloatV>(AFloat(-kSubnormalF32), -kSubnormalF32), //
+ })));
INSTANTIATE_TEST_SUITE_P(
- MatrixValueCannotBeRepresented,
- MaterializeAbstractNumeric, //
- testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented), //
- testing::ValuesIn(kMatrixMethods), //
- testing::Values(Types<f32M, AFloatM>(0.0_a, 3.5e+38), //
- Types<f32M, AFloatM>(0.0_a, -3.5e+38) //
- /* Types<f16M, AFloatM>(), */ //
- /* Types<f16M, AFloatM>(), */)));
+ MaterializeMatrix,
+ MaterializeAbstractNumericToDefaultType,
+ testing::Combine(testing::Values(Expectation::kMaterialize),
+ testing::ValuesIn(kMatrixMethods),
+ testing::ValuesIn(std::vector<Data>{
+ Types<f32M, AFloatM>(0.0_a, 0.0), //
+ Types<f32M, AFloatM>(1.0_a, 1.0), //
+ Types<f32M, AFloatM>(-1.0_a, -1.0), //
+ Types<f32M, AFloatM>(AFloat(kHighestF32), kHighestF32), //
+ Types<f32M, AFloatM>(AFloat(kLowestF32), kLowestF32), //
+ Types<f32M, AFloatM>(AFloat(kPiF32), kPiF64), //
+ Types<f32M, AFloatM>(AFloat(kSubnormalF32), kSubnormalF32), //
+ Types<f32M, AFloatM>(AFloat(-kSubnormalF32), -kSubnormalF32), //
+ })));
-} // namespace MaterializeTests
+INSTANTIATE_TEST_SUITE_P(MaterializeSwitch,
+ MaterializeAbstractNumericToDefaultType,
+ testing::Combine(testing::Values(Expectation::kMaterialize),
+ testing::ValuesIn(kSwitchMethods),
+ testing::ValuesIn(std::vector<Data>{
+ Types<i32, AInt>(0_a, 0.0), //
+ Types<i32, AInt>(AInt(kHighestI32), kHighestI32), //
+ Types<i32, AInt>(AInt(kLowestI32), kLowestI32), //
+ })));
+
+INSTANTIATE_TEST_SUITE_P(ScalarValueCannotBeRepresented,
+ MaterializeAbstractNumericToDefaultType,
+ testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented),
+ testing::ValuesIn(kScalarMethods),
+ testing::ValuesIn(std::vector<Data>{
+ Types<i32, AInt>(0_a, kHighestI32 + 1), //
+ Types<i32, AInt>(0_a, kLowestI32 - 1), //
+ Types<f32, AFloat>(0.0_a, kTooBigF32), //
+ Types<f32, AFloat>(0.0_a, -kTooBigF32), //
+ })));
+
+INSTANTIATE_TEST_SUITE_P(VectorValueCannotBeRepresented,
+ MaterializeAbstractNumericToDefaultType,
+ testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented),
+ testing::ValuesIn(kVectorMethods),
+ testing::ValuesIn(std::vector<Data>{
+ Types<i32V, AIntV>(0_a, kHighestI32 + 1), //
+ Types<i32V, AIntV>(0_a, kLowestI32 - 1), //
+ Types<i32V, AIntV>(0_a, kHighestU32 + 1), //
+ Types<f32V, AFloatV>(0.0_a, kTooBigF32), //
+ Types<f32V, AFloatV>(0.0_a, -kTooBigF32), //
+ })));
+
+INSTANTIATE_TEST_SUITE_P(MatrixValueCannotBeRepresented,
+ MaterializeAbstractNumericToDefaultType,
+ testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented),
+ testing::ValuesIn(kMatrixMethods),
+ testing::ValuesIn(std::vector<Data>{
+ Types<f32M, AFloatM>(0.0_a, kTooBigF32), //
+ Types<f32M, AFloatM>(0.0_a, -kTooBigF32), //
+ })));
+
+INSTANTIATE_TEST_SUITE_P(SwitchValueCannotBeRepresented,
+ MaterializeAbstractNumericToDefaultType,
+ testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented),
+ testing::ValuesIn(kSwitchMethods),
+ testing::ValuesIn(std::vector<Data>{
+ Types<i32, AInt>(0_a, kHighestI32 + 1), //
+ Types<i32, AInt>(0_a, kLowestI32 - 1), //
+ })));
+
+} // namespace materialize_abstract_numeric_to_default_type
} // namespace
} // namespace tint::resolver
diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc
index af8f16a..9fdb576 100644
--- a/src/tint/resolver/resolver.cc
+++ b/src/tint/resolver/resolver.cc
@@ -1145,7 +1145,7 @@
auto i32v = [&](uint32_t width) { return builder_->create<sem::Vector>(i32(), width); };
auto f32v = [&](uint32_t width) { return builder_->create<sem::Vector>(f32(), width); };
auto f32m = [&](uint32_t columns, uint32_t rows) {
- return builder_->create<sem::Matrix>(f32v(columns), rows);
+ return builder_->create<sem::Matrix>(f32v(rows), columns);
};
// Type dispatch based on the expression type