blob: 1b935eef0e91e765563e4d9af6425ae5483899b1 [file] [log] [blame]
Ben Clayton932418e2022-05-24 21:42:03 +00001// Copyright 2022 The Tint Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "src/tint/sem/materialize.h"
16
17#include "src/tint/resolver/resolver.h"
18#include "src/tint/resolver/resolver_test_helper.h"
19#include "src/tint/sem/test_helper.h"
20
21#include "gmock/gmock.h"
22
23using namespace tint::number_suffixes; // NOLINT
24
25namespace tint::resolver {
26namespace {
27
28using AFloatV = builder::vec<3, AFloat>;
29using AFloatM = builder::mat<3, 2, AFloat>;
30using AIntV = builder::vec<3, AInt>;
31using f32V = builder::vec<3, f32>;
32using f16V = builder::vec<3, f16>;
33using i32V = builder::vec<3, i32>;
34using u32V = builder::vec<3, u32>;
35using f32M = builder::mat<3, 2, f32>;
Ben Clayton22d8dea2022-06-20 19:23:02 +000036using i32Varr = builder::array<3, i32>;
Ben Clayton932418e2022-05-24 21:42:03 +000037
Ben Clayton3a236c62022-05-28 05:28:11 +000038constexpr double kHighestU32 = static_cast<double>(u32::kHighest);
39constexpr double kLowestU32 = static_cast<double>(u32::kLowest);
40constexpr double kHighestI32 = static_cast<double>(i32::kHighest);
41constexpr double kLowestI32 = static_cast<double>(i32::kLowest);
42constexpr double kHighestF32 = static_cast<double>(f32::kHighest);
43constexpr double kLowestF32 = static_cast<double>(f32::kLowest);
Zhaoming Jiang60588822022-06-28 14:03:36 +000044// constexpr double kHighestF16 = static_cast<double>(f16::kHighest);
45// constexpr double kLowestF16 = static_cast<double>(f16::kLowest);
Ben Clayton3a236c62022-05-28 05:28:11 +000046constexpr double kTooBigF32 = static_cast<double>(3.5e+38);
Zhaoming Jiang60588822022-06-28 14:03:36 +000047// constexpr double kTooBigF16 = static_cast<double>(6.6e+4);
Ben Clayton3a236c62022-05-28 05:28:11 +000048constexpr double kPiF64 = 3.141592653589793;
49constexpr double kPiF32 = 3.1415927410125732; // kPiF64 quantized to f32
Zhaoming Jiang60588822022-06-28 14:03:36 +000050// constexpr double kPiF16 = 3.140625; // kPiF64 quantized to f16
Ben Clayton3a236c62022-05-28 05:28:11 +000051
52constexpr double kSubnormalF32 = 0x1.0p-128;
Zhaoming Jiang60588822022-06-28 14:03:36 +000053// constexpr double kSubnormalF16 = 0x1.0p-16;
Ben Clayton3a236c62022-05-28 05:28:11 +000054
55enum class Expectation {
56 kMaterialize,
57 kNoMaterialize,
58 kInvalidConversion,
59 kValueCannotBeRepresented,
60};
61
62static std::ostream& operator<<(std::ostream& o, Expectation m) {
63 switch (m) {
64 case Expectation::kMaterialize:
65 return o << "materialize";
66 case Expectation::kNoMaterialize:
67 return o << "no-materialize";
68 case Expectation::kInvalidConversion:
69 return o << "invalid-conversion";
70 case Expectation::kValueCannotBeRepresented:
71 return o << "value cannot be represented";
72 }
73 return o << "<unknown>";
74}
75
Ben Claytonaa037ac2022-06-29 19:07:30 +000076template <typename CASE>
77class MaterializeTest : public resolver::ResolverTestWithParam<CASE> {
78 protected:
79 using ProgramBuilder::FriendlyName;
80
81 void CheckTypesAndValues(const sem::Expression* expr,
82 const tint::sem::Type* expected_sem_ty,
83 const std::variant<AInt, AFloat>& expected_value) {
84 std::visit([&](auto v) { CheckTypesAndValuesImpl(expr, expected_sem_ty, v); },
85 expected_value);
86 }
87
88 private:
89 template <typename T>
90 void CheckTypesAndValuesImpl(const sem::Expression* expr,
91 const tint::sem::Type* expected_sem_ty,
92 T expected_value) {
93 EXPECT_TYPE(expr->Type(), expected_sem_ty);
94
95 auto* value = expr->ConstantValue();
96 ASSERT_NE(value, nullptr);
97 EXPECT_TYPE(expr->Type(), value->Type());
98
99 tint::Switch(
100 expected_sem_ty, //
101 [&](const sem::Vector* v) {
102 for (uint32_t i = 0; i < v->Width(); i++) {
103 auto* el = value->Index(i);
104 ASSERT_NE(el, nullptr);
105 EXPECT_TYPE(el->Type(), v->type());
106 EXPECT_EQ(std::get<T>(el->Value()), expected_value);
107 }
108 },
109 [&](const sem::Matrix* m) {
110 for (uint32_t c = 0; c < m->columns(); c++) {
111 auto* column = value->Index(c);
112 ASSERT_NE(column, nullptr);
113 EXPECT_TYPE(column->Type(), m->ColumnType());
114 for (uint32_t r = 0; r < m->rows(); r++) {
115 auto* el = column->Index(r);
116 ASSERT_NE(el, nullptr);
117 EXPECT_TYPE(el->Type(), m->type());
118 EXPECT_EQ(std::get<T>(el->Value()), expected_value);
119 }
120 }
121 },
122 [&](Default) { EXPECT_EQ(std::get<T>(value->Value()), expected_value); });
123 }
124};
125
Ben Clayton3a236c62022-05-28 05:28:11 +0000126////////////////////////////////////////////////////////////////////////////////////////////////////
127// MaterializeAbstractNumericToConcreteType
128// Tests that an abstract-numeric will materialize to the expected concrete type
129////////////////////////////////////////////////////////////////////////////////////////////////////
130namespace materialize_abstract_numeric_to_concrete_type {
Ben Clayton932418e2022-05-24 21:42:03 +0000131// How should the materialization occur?
132enum class Method {
Ben Clayton3aa0f812022-05-27 22:06:26 +0000133 // var a : target_type = abstract_expr;
Ben Clayton932418e2022-05-24 21:42:03 +0000134 kVar,
135
Ben Clayton3aa0f812022-05-27 22:06:26 +0000136 // let a : target_type = abstract_expr;
Ben Clayton932418e2022-05-24 21:42:03 +0000137 kLet,
138
Ben Clayton22bd0042022-05-31 20:40:59 +0000139 // var a : target_type;
140 // a = abstract_expr;
141 kAssign,
142
143 // _ = abstract_expr;
144 kPhonyAssign,
145
Ben Clayton3aa0f812022-05-27 22:06:26 +0000146 // fn F(v : target_type) {}
Ben Clayton932418e2022-05-24 21:42:03 +0000147 // fn x() {
Ben Clayton3aa0f812022-05-27 22:06:26 +0000148 // F(abstract_expr);
Ben Clayton932418e2022-05-24 21:42:03 +0000149 // }
150 kFnArg,
151
Ben Clayton3aa0f812022-05-27 22:06:26 +0000152 // min(target_expr, abstract_expr);
Ben Clayton932418e2022-05-24 21:42:03 +0000153 kBuiltinArg,
154
Ben Clayton3aa0f812022-05-27 22:06:26 +0000155 // fn F() : target_type {
156 // return abstract_expr;
Ben Clayton932418e2022-05-24 21:42:03 +0000157 // }
158 kReturn,
159
Ben Clayton3aa0f812022-05-27 22:06:26 +0000160 // array<target_type, 1>(abstract_expr);
Ben Clayton932418e2022-05-24 21:42:03 +0000161 kArray,
162
163 // struct S {
Ben Clayton3aa0f812022-05-27 22:06:26 +0000164 // v : target_type
Ben Clayton932418e2022-05-24 21:42:03 +0000165 // };
166 // fn x() {
Ben Clayton3aa0f812022-05-27 22:06:26 +0000167 // _ = S(abstract_expr)
Ben Clayton932418e2022-05-24 21:42:03 +0000168 // }
169 kStruct,
170
Ben Clayton3aa0f812022-05-27 22:06:26 +0000171 // target_expr + abstract_expr
Ben Clayton932418e2022-05-24 21:42:03 +0000172 kBinaryOp,
173
Ben Clayton3aa0f812022-05-27 22:06:26 +0000174 // switch (abstract_expr) {
Ben Clayton932418e2022-05-24 21:42:03 +0000175 // case target_expr: {}
176 // default: {}
177 // }
178 kSwitchCond,
179
180 // switch (target_expr) {
Ben Clayton3aa0f812022-05-27 22:06:26 +0000181 // case abstract_expr: {}
Ben Clayton932418e2022-05-24 21:42:03 +0000182 // default: {}
183 // }
184 kSwitchCase,
185
Ben Clayton3aa0f812022-05-27 22:06:26 +0000186 // switch (abstract_expr) {
Ben Clayton932418e2022-05-24 21:42:03 +0000187 // case 123: {}
188 // case target_expr: {}
189 // default: {}
190 // }
191 kSwitchCondWithAbstractCase,
192
193 // switch (target_expr) {
194 // case 123: {}
Ben Clayton3aa0f812022-05-27 22:06:26 +0000195 // case abstract_expr: {}
Ben Clayton932418e2022-05-24 21:42:03 +0000196 // default: {}
197 // }
198 kSwitchCaseWithAbstractCase,
Ben Claytonb8ac93392022-05-28 10:34:06 +0000199
200 // @workgroup_size(target_expr, abstract_expr, 123)
dan sinclairb29892b2022-06-07 13:55:34 +0000201 // @compute
Ben Claytonb8ac93392022-05-28 10:34:06 +0000202 // fn f() {}
203 kWorkgroupSize
Ben Clayton932418e2022-05-24 21:42:03 +0000204};
205
206static std::ostream& operator<<(std::ostream& o, Method m) {
207 switch (m) {
208 case Method::kVar:
209 return o << "var";
210 case Method::kLet:
211 return o << "let";
Ben Clayton22bd0042022-05-31 20:40:59 +0000212 case Method::kAssign:
213 return o << "assign";
214 case Method::kPhonyAssign:
215 return o << "phony-assign";
Ben Clayton932418e2022-05-24 21:42:03 +0000216 case Method::kFnArg:
217 return o << "fn-arg";
218 case Method::kBuiltinArg:
219 return o << "builtin-arg";
220 case Method::kReturn:
221 return o << "return";
222 case Method::kArray:
223 return o << "array";
224 case Method::kStruct:
225 return o << "struct";
226 case Method::kBinaryOp:
227 return o << "binary-op";
228 case Method::kSwitchCond:
229 return o << "switch-cond";
230 case Method::kSwitchCase:
231 return o << "switch-case";
232 case Method::kSwitchCondWithAbstractCase:
233 return o << "switch-cond-with-abstract";
234 case Method::kSwitchCaseWithAbstractCase:
235 return o << "switch-case-with-abstract";
Ben Claytonb8ac93392022-05-28 10:34:06 +0000236 case Method::kWorkgroupSize:
237 return o << "workgroup-size";
Ben Clayton932418e2022-05-24 21:42:03 +0000238 }
239 return o << "<unknown>";
240}
241
242struct Data {
243 std::string target_type_name;
Ben Claytone34e0592022-05-25 21:16:55 +0000244 std::string target_element_type_name;
Ben Clayton932418e2022-05-24 21:42:03 +0000245 builder::ast_type_func_ptr target_ast_ty;
246 builder::sem_type_func_ptr target_sem_ty;
247 builder::ast_expr_func_ptr target_expr;
Ben Clayton3aa0f812022-05-27 22:06:26 +0000248 std::string abstract_type_name;
249 builder::ast_expr_func_ptr abstract_expr;
Ben Clayton932418e2022-05-24 21:42:03 +0000250 std::variant<AInt, AFloat> materialized_value;
Ben Claytone34e0592022-05-25 21:16:55 +0000251 double literal_value;
Ben Clayton932418e2022-05-24 21:42:03 +0000252};
253
Ben Clayton3aa0f812022-05-27 22:06:26 +0000254template <typename TARGET_TYPE, typename ABSTRACT_TYPE, typename MATERIALIZED_TYPE>
Ben Claytone34e0592022-05-25 21:16:55 +0000255Data Types(MATERIALIZED_TYPE materialized_value, double literal_value) {
256 using TargetDataType = builder::DataType<TARGET_TYPE>;
Ben Clayton3aa0f812022-05-27 22:06:26 +0000257 using AbstractDataType = builder::DataType<ABSTRACT_TYPE>;
Ben Claytone34e0592022-05-25 21:16:55 +0000258 using TargetElementDataType = builder::DataType<typename TargetDataType::ElementType>;
Ben Clayton932418e2022-05-24 21:42:03 +0000259 return {
Ben Claytone34e0592022-05-25 21:16:55 +0000260 TargetDataType::Name(), // target_type_name
261 TargetElementDataType::Name(), // target_element_type_name
262 TargetDataType::AST, // target_ast_ty
263 TargetDataType::Sem, // target_sem_ty
264 TargetDataType::Expr, // target_expr
Ben Clayton3aa0f812022-05-27 22:06:26 +0000265 AbstractDataType::Name(), // abstract_type_name
266 AbstractDataType::Expr, // abstract_expr
Ben Clayton932418e2022-05-24 21:42:03 +0000267 materialized_value,
Ben Claytone34e0592022-05-25 21:16:55 +0000268 literal_value,
269 };
270}
271
Ben Clayton3aa0f812022-05-27 22:06:26 +0000272template <typename TARGET_TYPE, typename ABSTRACT_TYPE>
Ben Claytone34e0592022-05-25 21:16:55 +0000273Data Types() {
274 using TargetDataType = builder::DataType<TARGET_TYPE>;
Ben Clayton3aa0f812022-05-27 22:06:26 +0000275 using AbstractDataType = builder::DataType<ABSTRACT_TYPE>;
Ben Claytone34e0592022-05-25 21:16:55 +0000276 using TargetElementDataType = builder::DataType<typename TargetDataType::ElementType>;
277 return {
278 TargetDataType::Name(), // target_type_name
279 TargetElementDataType::Name(), // target_element_type_name
280 TargetDataType::AST, // target_ast_ty
281 TargetDataType::Sem, // target_sem_ty
282 TargetDataType::Expr, // target_expr
Ben Clayton3aa0f812022-05-27 22:06:26 +0000283 AbstractDataType::Name(), // abstract_type_name
284 AbstractDataType::Expr, // abstract_expr
Ben Claytone34e0592022-05-25 21:16:55 +0000285 0_a,
286 0.0,
Ben Clayton932418e2022-05-24 21:42:03 +0000287 };
288}
289
290static std::ostream& operator<<(std::ostream& o, const Data& c) {
Ben Claytone34e0592022-05-25 21:16:55 +0000291 auto print_value = [&](auto&& v) { o << v; };
Ben Clayton3aa0f812022-05-27 22:06:26 +0000292 o << "[" << c.target_type_name << " <- " << c.abstract_type_name << "] [";
Ben Claytone34e0592022-05-25 21:16:55 +0000293 std::visit(print_value, c.materialized_value);
294 o << " <- " << c.literal_value << "]";
295 return o;
Ben Clayton932418e2022-05-24 21:42:03 +0000296}
297
Ben Clayton3a236c62022-05-28 05:28:11 +0000298using MaterializeAbstractNumericToConcreteType =
Ben Claytonaa037ac2022-06-29 19:07:30 +0000299 MaterializeTest<std::tuple<Expectation, Method, Data>>;
Ben Clayton932418e2022-05-24 21:42:03 +0000300
Ben Clayton3a236c62022-05-28 05:28:11 +0000301TEST_P(MaterializeAbstractNumericToConcreteType, Test) {
Zhaoming Jiang60588822022-06-28 14:03:36 +0000302 // Once built-in and ops using f16 is properly supported, we'll need to enable this:
Ben Clayton932418e2022-05-24 21:42:03 +0000303 // Enable(ast::Extension::kF16);
304
305 const auto& param = GetParam();
306 const auto& expectation = std::get<0>(param);
307 const auto& method = std::get<1>(param);
308 const auto& data = std::get<2>(param);
309
310 auto target_ty = [&] { return data.target_ast_ty(*this); };
311 auto target_expr = [&] { return data.target_expr(*this, 42); };
Ben Clayton3aa0f812022-05-27 22:06:26 +0000312 auto* abstract_expr = data.abstract_expr(*this, data.literal_value);
Ben Clayton932418e2022-05-24 21:42:03 +0000313 switch (method) {
314 case Method::kVar:
Ben Clayton3aa0f812022-05-27 22:06:26 +0000315 WrapInFunction(Decl(Var("a", target_ty(), abstract_expr)));
Ben Clayton932418e2022-05-24 21:42:03 +0000316 break;
317 case Method::kLet:
Ben Clayton3aa0f812022-05-27 22:06:26 +0000318 WrapInFunction(Decl(Let("a", target_ty(), abstract_expr)));
Ben Clayton932418e2022-05-24 21:42:03 +0000319 break;
Ben Clayton22bd0042022-05-31 20:40:59 +0000320 case Method::kAssign:
321 WrapInFunction(Decl(Var("a", target_ty(), nullptr)), Assign("a", abstract_expr));
322 break;
323 case Method::kPhonyAssign:
324 WrapInFunction(Assign(Phony(), abstract_expr));
325 break;
Ben Clayton932418e2022-05-24 21:42:03 +0000326 case Method::kFnArg:
327 Func("F", {Param("P", target_ty())}, ty.void_(), {});
Ben Clayton3aa0f812022-05-27 22:06:26 +0000328 WrapInFunction(CallStmt(Call("F", abstract_expr)));
Ben Clayton932418e2022-05-24 21:42:03 +0000329 break;
330 case Method::kBuiltinArg:
Ben Clayton3aa0f812022-05-27 22:06:26 +0000331 WrapInFunction(CallStmt(Call("min", target_expr(), abstract_expr)));
Ben Clayton932418e2022-05-24 21:42:03 +0000332 break;
333 case Method::kReturn:
Ben Clayton3aa0f812022-05-27 22:06:26 +0000334 Func("F", {}, target_ty(), {Return(abstract_expr)});
Ben Clayton932418e2022-05-24 21:42:03 +0000335 break;
336 case Method::kArray:
Ben Clayton3aa0f812022-05-27 22:06:26 +0000337 WrapInFunction(Construct(ty.array(target_ty(), 1_i), abstract_expr));
Ben Clayton932418e2022-05-24 21:42:03 +0000338 break;
339 case Method::kStruct:
340 Structure("S", {Member("v", target_ty())});
Ben Clayton3aa0f812022-05-27 22:06:26 +0000341 WrapInFunction(Construct(ty.type_name("S"), abstract_expr));
Ben Clayton932418e2022-05-24 21:42:03 +0000342 break;
343 case Method::kBinaryOp:
Ben Clayton3aa0f812022-05-27 22:06:26 +0000344 WrapInFunction(Add(target_expr(), abstract_expr));
Ben Clayton932418e2022-05-24 21:42:03 +0000345 break;
346 case Method::kSwitchCond:
Ben Clayton3aa0f812022-05-27 22:06:26 +0000347 WrapInFunction(Switch(abstract_expr, //
Ben Clayton932418e2022-05-24 21:42:03 +0000348 Case(target_expr()->As<ast::IntLiteralExpression>()), //
349 DefaultCase()));
350 break;
351 case Method::kSwitchCase:
Ben Clayton3aa0f812022-05-27 22:06:26 +0000352 WrapInFunction(Switch(target_expr(), //
353 Case(abstract_expr->As<ast::IntLiteralExpression>()), //
Ben Clayton932418e2022-05-24 21:42:03 +0000354 DefaultCase()));
355 break;
356 case Method::kSwitchCondWithAbstractCase:
Ben Clayton3aa0f812022-05-27 22:06:26 +0000357 WrapInFunction(Switch(abstract_expr, //
Ben Clayton932418e2022-05-24 21:42:03 +0000358 Case(Expr(123_a)), //
359 Case(target_expr()->As<ast::IntLiteralExpression>()), //
360 DefaultCase()));
361 break;
362 case Method::kSwitchCaseWithAbstractCase:
Ben Clayton3aa0f812022-05-27 22:06:26 +0000363 WrapInFunction(Switch(target_expr(), //
364 Case(Expr(123_a)), //
365 Case(abstract_expr->As<ast::IntLiteralExpression>()), //
Ben Clayton932418e2022-05-24 21:42:03 +0000366 DefaultCase()));
367 break;
Ben Claytonb8ac93392022-05-28 10:34:06 +0000368 case Method::kWorkgroupSize:
369 Func("f", {}, ty.void_(), {},
370 {WorkgroupSize(target_expr(), abstract_expr, Expr(123_a)),
371 Stage(ast::PipelineStage::kCompute)});
372 break;
Ben Clayton932418e2022-05-24 21:42:03 +0000373 }
374
Ben Clayton932418e2022-05-24 21:42:03 +0000375 switch (expectation) {
376 case Expectation::kMaterialize: {
377 ASSERT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton3aa0f812022-05-27 22:06:26 +0000378 auto* materialize = Sem().Get<sem::Materialize>(abstract_expr);
Ben Clayton932418e2022-05-24 21:42:03 +0000379 ASSERT_NE(materialize, nullptr);
Ben Claytonaa037ac2022-06-29 19:07:30 +0000380 CheckTypesAndValues(materialize, data.target_sem_ty(*this), data.materialized_value);
Ben Clayton932418e2022-05-24 21:42:03 +0000381 break;
382 }
383 case Expectation::kNoMaterialize: {
384 ASSERT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton3aa0f812022-05-27 22:06:26 +0000385 auto* sem = Sem().Get(abstract_expr);
Ben Clayton932418e2022-05-24 21:42:03 +0000386 ASSERT_NE(sem, nullptr);
387 EXPECT_FALSE(sem->Is<sem::Materialize>());
Ben Claytonaa037ac2022-06-29 19:07:30 +0000388 CheckTypesAndValues(sem, data.target_sem_ty(*this), data.materialized_value);
Ben Clayton932418e2022-05-24 21:42:03 +0000389 break;
390 }
Ben Clayton3a236c62022-05-28 05:28:11 +0000391 case Expectation::kInvalidConversion: {
Ben Clayton932418e2022-05-24 21:42:03 +0000392 ASSERT_FALSE(r()->Resolve());
393 std::string expect;
394 switch (method) {
395 case Method::kBuiltinArg:
396 expect = "error: no matching call to min(" + data.target_type_name + ", " +
Ben Clayton3aa0f812022-05-27 22:06:26 +0000397 data.abstract_type_name + ")";
Ben Clayton932418e2022-05-24 21:42:03 +0000398 break;
399 case Method::kBinaryOp:
400 expect = "error: no matching overload for operator + (" +
Ben Clayton3aa0f812022-05-27 22:06:26 +0000401 data.target_type_name + ", " + data.abstract_type_name + ")";
Ben Clayton932418e2022-05-24 21:42:03 +0000402 break;
403 default:
Ben Clayton3aa0f812022-05-27 22:06:26 +0000404 expect = "error: cannot convert value of type '" + data.abstract_type_name +
Ben Clayton932418e2022-05-24 21:42:03 +0000405 "' to type '" + data.target_type_name + "'";
406 break;
407 }
408 EXPECT_THAT(r()->error(), testing::StartsWith(expect));
409 break;
410 }
Ben Claytone34e0592022-05-25 21:16:55 +0000411 case Expectation::kValueCannotBeRepresented:
412 ASSERT_FALSE(r()->Resolve());
413 EXPECT_THAT(r()->error(), testing::HasSubstr("cannot be represented as '" +
414 data.target_element_type_name + "'"));
415 break;
Ben Clayton932418e2022-05-24 21:42:03 +0000416 }
417}
418
Ben Claytone34e0592022-05-25 21:16:55 +0000419/// Methods that support scalar materialization
Ben Clayton3a236c62022-05-28 05:28:11 +0000420constexpr Method kScalarMethods[] = {
Ben Clayton22bd0042022-05-31 20:40:59 +0000421 Method::kLet, Method::kVar, Method::kAssign, Method::kFnArg, Method::kBuiltinArg,
Ben Clayton3a236c62022-05-28 05:28:11 +0000422 Method::kReturn, Method::kArray, Method::kStruct, Method::kBinaryOp,
423};
Ben Clayton932418e2022-05-24 21:42:03 +0000424
Ben Claytone34e0592022-05-25 21:16:55 +0000425/// Methods that support vector materialization
Ben Clayton3a236c62022-05-28 05:28:11 +0000426constexpr Method kVectorMethods[] = {
Ben Clayton22bd0042022-05-31 20:40:59 +0000427 Method::kLet, Method::kVar, Method::kAssign, Method::kFnArg, Method::kBuiltinArg,
Ben Clayton3a236c62022-05-28 05:28:11 +0000428 Method::kReturn, Method::kArray, Method::kStruct, Method::kBinaryOp,
429};
Ben Clayton932418e2022-05-24 21:42:03 +0000430
Ben Claytone34e0592022-05-25 21:16:55 +0000431/// Methods that support matrix materialization
Ben Clayton3a236c62022-05-28 05:28:11 +0000432constexpr Method kMatrixMethods[] = {
Ben Clayton22bd0042022-05-31 20:40:59 +0000433 Method::kLet, Method::kVar, Method::kAssign, Method::kFnArg,
434 Method::kReturn, Method::kArray, Method::kStruct, Method::kBinaryOp,
Ben Clayton3a236c62022-05-28 05:28:11 +0000435};
Ben Clayton932418e2022-05-24 21:42:03 +0000436
Ben Claytone34e0592022-05-25 21:16:55 +0000437/// Methods that support materialization for switch cases
Ben Clayton3a236c62022-05-28 05:28:11 +0000438constexpr Method kSwitchMethods[] = {
439 Method::kSwitchCond,
440 Method::kSwitchCase,
441 Method::kSwitchCondWithAbstractCase,
442 Method::kSwitchCaseWithAbstractCase,
443};
Ben Claytone34e0592022-05-25 21:16:55 +0000444
Ben Clayton22bd0042022-05-31 20:40:59 +0000445/// Methods that do not materialize
446constexpr Method kNoMaterializeMethods[] = {
447 Method::kPhonyAssign,
Ben Claytonaa037ac2022-06-29 19:07:30 +0000448 // TODO(crbug.com/tint/1504): Enable once we have abstract overloads of builtins / binary
449 // ops: Method::kBuiltinArg, Method::kBinaryOp,
Ben Clayton22bd0042022-05-31 20:40:59 +0000450};
Ben Claytone34e0592022-05-25 21:16:55 +0000451INSTANTIATE_TEST_SUITE_P(
452 MaterializeScalar,
Ben Clayton3a236c62022-05-28 05:28:11 +0000453 MaterializeAbstractNumericToConcreteType,
454 testing::Combine(testing::Values(Expectation::kMaterialize),
455 testing::ValuesIn(kScalarMethods),
456 testing::ValuesIn(std::vector<Data>{
Zhaoming Jiang60588822022-06-28 14:03:36 +0000457 Types<i32, AInt>(0_a, 0.0), //
458 Types<i32, AInt>(1_a, 1.0), //
459 Types<i32, AInt>(-1_a, -1.0), //
460 Types<i32, AInt>(AInt(kHighestI32), kHighestI32), //
461 Types<i32, AInt>(AInt(kLowestI32), kLowestI32), //
462 Types<u32, AInt>(0_a, 0.0), //
463 Types<u32, AInt>(1_a, 1.0), //
464 Types<u32, AInt>(AInt(kHighestU32), kHighestU32), //
465 Types<u32, AInt>(AInt(kLowestU32), kLowestU32), //
466 Types<f32, AFloat>(0.0_a, 0.0), //
467 Types<f32, AFloat>(AFloat(kHighestF32), kHighestF32), //
468 Types<f32, AFloat>(AFloat(kLowestF32), kLowestF32), //
469 Types<f32, AFloat>(AFloat(kPiF32), kPiF64), //
470 Types<f32, AFloat>(AFloat(kSubnormalF32), kSubnormalF32), //
471 Types<f32, AFloat>(AFloat(-kSubnormalF32), -kSubnormalF32), //
472 /* Types<f16, AFloat>(0.0_a, 0.0), */ //
473 /* Types<f16, AFloat>(1.0_a, 1.0), */ //
474 /* Types<f16, AFloat>(AFloat(kHighestF16), kHighestF16), */ //
475 /* Types<f16, AFloat>(AFloat(kLowestF16), kLowestF16), */ //
476 /* Types<f16, AFloat>(AFloat(kPiF16), kPiF64), */ //
477 /* Types<f16, AFloat>(AFloat(kSubnormalF16), kSubnormalF16), */ //
478 /* Types<f16, AFloat>(AFloat(-kSubnormalF16), -kSubnormalF16), */ //
Ben Clayton3a236c62022-05-28 05:28:11 +0000479 })));
Ben Claytone34e0592022-05-25 21:16:55 +0000480
481INSTANTIATE_TEST_SUITE_P(
482 MaterializeVector,
Ben Clayton3a236c62022-05-28 05:28:11 +0000483 MaterializeAbstractNumericToConcreteType,
484 testing::Combine(testing::Values(Expectation::kMaterialize),
485 testing::ValuesIn(kVectorMethods),
486 testing::ValuesIn(std::vector<Data>{
Zhaoming Jiang60588822022-06-28 14:03:36 +0000487 Types<i32V, AIntV>(0_a, 0.0), //
488 Types<i32V, AIntV>(1_a, 1.0), //
489 Types<i32V, AIntV>(-1_a, -1.0), //
490 Types<i32V, AIntV>(AInt(kHighestI32), kHighestI32), //
491 Types<i32V, AIntV>(AInt(kLowestI32), kLowestI32), //
492 Types<u32V, AIntV>(0_a, 0.0), //
493 Types<u32V, AIntV>(1_a, 1.0), //
494 Types<u32V, AIntV>(AInt(kHighestU32), kHighestU32), //
495 Types<u32V, AIntV>(AInt(kLowestU32), kLowestU32), //
496 Types<f32V, AFloatV>(0.0_a, 0.0), //
497 Types<f32V, AFloatV>(1.0_a, 1.0), //
498 Types<f32V, AFloatV>(-1.0_a, -1.0), //
499 Types<f32V, AFloatV>(AFloat(kHighestF32), kHighestF32), //
500 Types<f32V, AFloatV>(AFloat(kLowestF32), kLowestF32), //
501 Types<f32V, AFloatV>(AFloat(kPiF32), kPiF64), //
502 Types<f32V, AFloatV>(AFloat(kSubnormalF32), kSubnormalF32), //
503 Types<f32V, AFloatV>(AFloat(-kSubnormalF32), -kSubnormalF32), //
504 /* Types<f16V, AFloatV>(0.0_a, 0.0), */ //
505 /* Types<f16V, AFloatV>(1.0_a, 1.0), */ //
506 /* Types<f16V, AFloatV>(-1.0_a, -1.0), */ //
507 /* Types<f16V, AFloatV>(AFloat(kHighestF16), kHighestF16), */ //
508 /* Types<f16V, AFloatV>(AFloat(kLowestF16), kLowestF16), */ //
509 /* Types<f16V, AFloatV>(AFloat(kPiF16), kPiF64), */ //
510 /* Types<f16V, AFloatV>(AFloat(kSubnormalF16), kSubnormalF16), */ //
511 /* Types<f16V, AFloatV>(AFloat(-kSubnormalF16), -kSubnormalF16), */ //
Ben Clayton3a236c62022-05-28 05:28:11 +0000512 })));
Ben Claytone34e0592022-05-25 21:16:55 +0000513
514INSTANTIATE_TEST_SUITE_P(
515 MaterializeMatrix,
Ben Clayton3a236c62022-05-28 05:28:11 +0000516 MaterializeAbstractNumericToConcreteType,
517 testing::Combine(testing::Values(Expectation::kMaterialize),
518 testing::ValuesIn(kMatrixMethods),
519 testing::ValuesIn(std::vector<Data>{
Zhaoming Jiang60588822022-06-28 14:03:36 +0000520 Types<f32M, AFloatM>(0.0_a, 0.0), //
521 Types<f32M, AFloatM>(1.0_a, 1.0), //
522 Types<f32M, AFloatM>(-1.0_a, -1.0), //
523 Types<f32M, AFloatM>(AFloat(kHighestF32), kHighestF32), //
524 Types<f32M, AFloatM>(AFloat(kLowestF32), kLowestF32), //
525 Types<f32M, AFloatM>(AFloat(kPiF32), kPiF64), //
526 Types<f32M, AFloatM>(AFloat(kSubnormalF32), kSubnormalF32), //
527 Types<f32M, AFloatM>(AFloat(-kSubnormalF32), -kSubnormalF32), //
528 /* Types<f16M, AFloatM>(0.0_a, 0.0), */ //
529 /* Types<f16M, AFloatM>(1.0_a, 1.0), */ //
530 /* Types<f16M, AFloatM>(-1.0_a, -1.0), */ //
531 /* Types<f16M, AFloatM>(AFloat(kHighestF16), kHighestF16), */ //
532 /* Types<f16M, AFloatM>(AFloat(kLowestF16), kLowestF16), */ //
533 /* Types<f16M, AFloatM>(AFloat(kPiF16), kPiF64), */ //
534 /* Types<f16M, AFloatM>(AFloat(kSubnormalF16), kSubnormalF16), */ //
535 /* Types<f16M, AFloatM>(AFloat(-kSubnormalF16), -kSubnormalF16), */ //
Ben Clayton3a236c62022-05-28 05:28:11 +0000536 })));
Ben Claytone34e0592022-05-25 21:16:55 +0000537
Ben Clayton3a236c62022-05-28 05:28:11 +0000538INSTANTIATE_TEST_SUITE_P(MaterializeSwitch,
539 MaterializeAbstractNumericToConcreteType,
540 testing::Combine(testing::Values(Expectation::kMaterialize),
541 testing::ValuesIn(kSwitchMethods),
542 testing::ValuesIn(std::vector<Data>{
543 Types<i32, AInt>(0_a, 0.0), //
544 Types<i32, AInt>(1_a, 1.0), //
545 Types<i32, AInt>(-1_a, -1.0), //
546 Types<i32, AInt>(AInt(kHighestI32), kHighestI32), //
547 Types<i32, AInt>(AInt(kLowestI32), kLowestI32), //
548 Types<u32, AInt>(0_a, 0.0), //
549 Types<u32, AInt>(1_a, 1.0), //
550 Types<u32, AInt>(AInt(kHighestU32), kHighestU32), //
551 Types<u32, AInt>(AInt(kLowestU32), kLowestU32), //
552 })));
Ben Clayton932418e2022-05-24 21:42:03 +0000553
Ben Claytonb8ac93392022-05-28 10:34:06 +0000554INSTANTIATE_TEST_SUITE_P(MaterializeWorkgroupSize,
555 MaterializeAbstractNumericToConcreteType,
556 testing::Combine(testing::Values(Expectation::kMaterialize),
557 testing::Values(Method::kWorkgroupSize),
558 testing::ValuesIn(std::vector<Data>{
559 Types<i32, AInt>(1_a, 1.0), //
560 Types<i32, AInt>(10_a, 10.0), //
561 Types<i32, AInt>(65535_a, 65535.0), //
562 Types<u32, AInt>(1_a, 1.0), //
563 Types<u32, AInt>(10_a, 10.0), //
564 Types<u32, AInt>(65535_a, 65535.0), //
565 })));
566
Ben Clayton22bd0042022-05-31 20:40:59 +0000567INSTANTIATE_TEST_SUITE_P(NoMaterialize,
Ben Clayton3a236c62022-05-28 05:28:11 +0000568 MaterializeAbstractNumericToConcreteType,
569 testing::Combine(testing::Values(Expectation::kNoMaterialize),
Ben Clayton22bd0042022-05-31 20:40:59 +0000570 testing::ValuesIn(kNoMaterializeMethods),
Ben Clayton3a236c62022-05-28 05:28:11 +0000571 testing::ValuesIn(std::vector<Data>{
Ben Clayton22bd0042022-05-31 20:40:59 +0000572 Types<AInt, AInt>(1_a, 1_a), //
573 Types<AIntV, AIntV>(1_a, 1_a), //
574 Types<AFloat, AFloat>(1.0_a, 1.0_a), //
575 Types<AFloatV, AFloatV>(1.0_a, 1.0_a), //
576 Types<AFloatM, AFloatM>(1.0_a, 1.0_a), //
Ben Clayton3a236c62022-05-28 05:28:11 +0000577 })));
Ben Clayton22bd0042022-05-31 20:40:59 +0000578
Ben Clayton3a236c62022-05-28 05:28:11 +0000579INSTANTIATE_TEST_SUITE_P(InvalidConversion,
580 MaterializeAbstractNumericToConcreteType,
581 testing::Combine(testing::Values(Expectation::kInvalidConversion),
582 testing::ValuesIn(kScalarMethods),
583 testing::ValuesIn(std::vector<Data>{
Ben Clayton22d8dea2022-06-20 19:23:02 +0000584 Types<i32, AFloat>(), //
585 Types<u32, AFloat>(), //
586 Types<i32V, AFloatV>(), //
587 Types<u32V, AFloatV>(), //
588 Types<i32Varr, AInt>(), //
589 Types<i32Varr, AIntV>(), //
590 Types<i32Varr, AFloat>(), //
591 Types<i32Varr, AFloatV>(), //
Ben Clayton3a236c62022-05-28 05:28:11 +0000592 })));
593
594INSTANTIATE_TEST_SUITE_P(ScalarValueCannotBeRepresented,
595 MaterializeAbstractNumericToConcreteType,
596 testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented),
597 testing::ValuesIn(kScalarMethods),
598 testing::ValuesIn(std::vector<Data>{
Zhaoming Jiang60588822022-06-28 14:03:36 +0000599 Types<i32, AInt>(0_a, kHighestI32 + 1), //
600 Types<i32, AInt>(0_a, kLowestI32 - 1), //
601 Types<u32, AInt>(0_a, kHighestU32 + 1), //
602 Types<u32, AInt>(0_a, kLowestU32 - 1), //
603 Types<f32, AFloat>(0.0_a, kTooBigF32), //
604 Types<f32, AFloat>(0.0_a, -kTooBigF32), //
605 /* Types<f16, AFloat>(0.0_a, kTooBigF16), */ //
606 /* Types<f16, AFloat>(0.0_a, -kTooBigF16), */ //
Ben Clayton3a236c62022-05-28 05:28:11 +0000607 })));
608
609INSTANTIATE_TEST_SUITE_P(VectorValueCannotBeRepresented,
610 MaterializeAbstractNumericToConcreteType,
611 testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented),
612 testing::ValuesIn(kVectorMethods),
613 testing::ValuesIn(std::vector<Data>{
Zhaoming Jiang60588822022-06-28 14:03:36 +0000614 Types<i32V, AIntV>(0_a, kHighestI32 + 1), //
615 Types<i32V, AIntV>(0_a, kLowestI32 - 1), //
616 Types<u32V, AIntV>(0_a, kHighestU32 + 1), //
617 Types<u32V, AIntV>(0_a, kLowestU32 - 1), //
618 Types<f32V, AFloatV>(0.0_a, kTooBigF32), //
619 Types<f32V, AFloatV>(0.0_a, -kTooBigF32), //
620 /* Types<f16V, AFloatV>(0.0_a, kTooBigF16), */ //
621 /* Types<f16V, AFloatV>(0.0_a, -kTooBigF16), */ //
Ben Clayton3a236c62022-05-28 05:28:11 +0000622 })));
623
624INSTANTIATE_TEST_SUITE_P(MatrixValueCannotBeRepresented,
625 MaterializeAbstractNumericToConcreteType,
626 testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented),
627 testing::ValuesIn(kMatrixMethods),
628 testing::ValuesIn(std::vector<Data>{
Zhaoming Jiang60588822022-06-28 14:03:36 +0000629 Types<f32M, AFloatM>(0.0_a, kTooBigF32), //
630 Types<f32M, AFloatM>(0.0_a, -kTooBigF32), //
631 /* Types<f16M, AFloatM>(0.0_a, kTooBigF16), */ //
632 /* Types<f16M, AFloatM>(0.0_a, -kTooBigF16), */ //
Ben Clayton3a236c62022-05-28 05:28:11 +0000633 })));
634
635} // namespace materialize_abstract_numeric_to_concrete_type
636
637////////////////////////////////////////////////////////////////////////////////////////////////////
638// Tests that in the absence of a 'target type' an abstract-int will materialize to i32, and an
639// abstract-float will materialize to f32.
640////////////////////////////////////////////////////////////////////////////////////////////////////
641namespace materialize_abstract_numeric_to_default_type {
642
643// How should the materialization occur?
644enum class Method {
645 // var a = abstract_expr;
646 kVar,
647
648 // let a = abstract_expr;
649 kLet,
650
Ben Clayton49a09142022-05-31 15:22:21 +0000651 // min(abstract_expr, abstract_expr)
Ben Clayton3a236c62022-05-28 05:28:11 +0000652 kBuiltinArg,
653
Ben Clayton49a09142022-05-31 15:22:21 +0000654 // bitcast<f32>(abstract_expr)
Ben Clayton8c7ffbd2022-05-28 07:09:17 +0000655 kBitcastF32Arg,
656
Ben Clayton49a09142022-05-31 15:22:21 +0000657 // bitcast<vec3<f32>>(abstract_expr)
Ben Clayton8c7ffbd2022-05-28 07:09:17 +0000658 kBitcastVec3F32Arg,
659
Ben Clayton49a09142022-05-31 15:22:21 +0000660 // array<i32, abstract_expr>()
Ben Clayton3a236c62022-05-28 05:28:11 +0000661 kArrayLength,
662
663 // switch (abstract_expr) {
664 // case abstract_expr: {}
665 // default: {}
666 // }
667 kSwitch,
Ben Claytonb8ac93392022-05-28 10:34:06 +0000668
669 // @workgroup_size(abstract_expr)
dan sinclairb29892b2022-06-07 13:55:34 +0000670 // @compute
Ben Claytonb8ac93392022-05-28 10:34:06 +0000671 // fn f() {}
Ben Clayton49a09142022-05-31 15:22:21 +0000672 kWorkgroupSize,
673
674 // arr[abstract_expr]
675 kIndex,
Ben Clayton3a236c62022-05-28 05:28:11 +0000676};
677
678static std::ostream& operator<<(std::ostream& o, Method m) {
679 switch (m) {
680 case Method::kVar:
681 return o << "var";
682 case Method::kLet:
683 return o << "let";
684 case Method::kBuiltinArg:
685 return o << "builtin-arg";
Ben Clayton8c7ffbd2022-05-28 07:09:17 +0000686 case Method::kBitcastF32Arg:
687 return o << "bitcast-f32-arg";
688 case Method::kBitcastVec3F32Arg:
689 return o << "bitcast-vec3-f32-arg";
Ben Clayton3a236c62022-05-28 05:28:11 +0000690 case Method::kArrayLength:
691 return o << "array-length";
692 case Method::kSwitch:
693 return o << "switch";
Ben Claytonb8ac93392022-05-28 10:34:06 +0000694 case Method::kWorkgroupSize:
695 return o << "workgroup-size";
Ben Clayton49a09142022-05-31 15:22:21 +0000696 case Method::kIndex:
697 return o << "index";
Ben Clayton3a236c62022-05-28 05:28:11 +0000698 }
699 return o << "<unknown>";
700}
701
702struct Data {
703 std::string expected_type_name;
704 std::string expected_element_type_name;
705 builder::sem_type_func_ptr expected_sem_ty;
706 std::string abstract_type_name;
707 builder::ast_expr_func_ptr abstract_expr;
708 std::variant<AInt, AFloat> materialized_value;
709 double literal_value;
710};
711
712template <typename EXPECTED_TYPE, typename ABSTRACT_TYPE, typename MATERIALIZED_TYPE>
713Data Types(MATERIALIZED_TYPE materialized_value, double literal_value) {
714 using ExpectedDataType = builder::DataType<EXPECTED_TYPE>;
715 using AbstractDataType = builder::DataType<ABSTRACT_TYPE>;
716 using TargetElementDataType = builder::DataType<typename ExpectedDataType::ElementType>;
717 return {
718 ExpectedDataType::Name(), // expected_type_name
719 TargetElementDataType::Name(), // expected_element_type_name
720 ExpectedDataType::Sem, // expected_sem_ty
721 AbstractDataType::Name(), // abstract_type_name
722 AbstractDataType::Expr, // abstract_expr
723 materialized_value,
724 literal_value,
725 };
726}
727
728static std::ostream& operator<<(std::ostream& o, const Data& c) {
729 auto print_value = [&](auto&& v) { o << v; };
730 o << "[" << c.expected_type_name << " <- " << c.abstract_type_name << "] [";
731 std::visit(print_value, c.materialized_value);
732 o << " <- " << c.literal_value << "]";
733 return o;
734}
735
736using MaterializeAbstractNumericToDefaultType =
Ben Claytonaa037ac2022-06-29 19:07:30 +0000737 MaterializeTest<std::tuple<Expectation, Method, Data>>;
Ben Clayton3a236c62022-05-28 05:28:11 +0000738
739TEST_P(MaterializeAbstractNumericToDefaultType, Test) {
Ben Clayton3a236c62022-05-28 05:28:11 +0000740 const auto& param = GetParam();
741 const auto& expectation = std::get<0>(param);
742 const auto& method = std::get<1>(param);
743 const auto& data = std::get<2>(param);
744
745 ast::ExpressionList abstract_exprs;
746 auto abstract_expr = [&] {
747 auto* expr = data.abstract_expr(*this, data.literal_value);
748 abstract_exprs.emplace_back(expr);
749 return expr;
750 };
751 switch (method) {
752 case Method::kVar:
753 WrapInFunction(Decl(Var("a", nullptr, abstract_expr())));
754 break;
755 case Method::kLet:
756 WrapInFunction(Decl(Let("a", nullptr, abstract_expr())));
757 break;
758 case Method::kBuiltinArg:
759 WrapInFunction(CallStmt(Call("min", abstract_expr(), abstract_expr())));
760 break;
Ben Clayton8c7ffbd2022-05-28 07:09:17 +0000761 case Method::kBitcastF32Arg:
762 WrapInFunction(Bitcast<f32>(abstract_expr()));
763 break;
764 case Method::kBitcastVec3F32Arg:
765 WrapInFunction(Bitcast(ty.vec3<f32>(), abstract_expr()));
766 break;
Ben Clayton3a236c62022-05-28 05:28:11 +0000767 case Method::kArrayLength:
768 WrapInFunction(Construct(ty.array(ty.i32(), abstract_expr())));
769 break;
770 case Method::kSwitch:
771 WrapInFunction(Switch(abstract_expr(),
772 Case(abstract_expr()->As<ast::IntLiteralExpression>()),
773 DefaultCase()));
774 break;
Ben Claytonb8ac93392022-05-28 10:34:06 +0000775 case Method::kWorkgroupSize:
776 Func("f", {}, ty.void_(), {},
777 {WorkgroupSize(abstract_expr()), Stage(ast::PipelineStage::kCompute)});
778 break;
Ben Clayton49a09142022-05-31 15:22:21 +0000779 case Method::kIndex:
Ben Clayton01208e72022-06-25 08:12:59 +0000780 GlobalVar("arr", ty.array<i32, 4>(), ast::StorageClass::kPrivate);
Ben Clayton49a09142022-05-31 15:22:21 +0000781 WrapInFunction(IndexAccessor("arr", abstract_expr()));
782 break;
Ben Clayton3a236c62022-05-28 05:28:11 +0000783 }
784
Ben Clayton3a236c62022-05-28 05:28:11 +0000785 switch (expectation) {
786 case Expectation::kMaterialize: {
787 ASSERT_TRUE(r()->Resolve()) << r()->error();
788 for (auto* expr : abstract_exprs) {
789 auto* materialize = Sem().Get<sem::Materialize>(expr);
790 ASSERT_NE(materialize, nullptr);
Ben Claytonaa037ac2022-06-29 19:07:30 +0000791 CheckTypesAndValues(materialize, data.expected_sem_ty(*this),
792 data.materialized_value);
Ben Clayton3a236c62022-05-28 05:28:11 +0000793 }
794 break;
795 }
796 case Expectation::kInvalidConversion: {
797 ASSERT_FALSE(r()->Resolve());
798 std::string expect;
799 switch (method) {
800 case Method::kBuiltinArg:
801 expect = "error: no matching call to min(" + data.abstract_type_name + ", " +
802 data.abstract_type_name + ")";
803 break;
804 default:
805 expect = "error: cannot convert value of type '" + data.abstract_type_name +
806 "' to type '" + data.expected_type_name + "'";
807 break;
808 }
809 EXPECT_THAT(r()->error(), testing::StartsWith(expect));
810 break;
811 }
812 case Expectation::kValueCannotBeRepresented:
813 ASSERT_FALSE(r()->Resolve());
814 EXPECT_THAT(r()->error(), testing::HasSubstr("cannot be represented as '" +
815 data.expected_element_type_name + "'"));
816 break;
817 default:
818 FAIL() << "unhandled expectation: " << expectation;
819 }
820}
821
822/// Methods that support scalar materialization
823constexpr Method kScalarMethods[] = {
824 Method::kLet,
825 Method::kVar,
826 Method::kBuiltinArg,
Ben Clayton8c7ffbd2022-05-28 07:09:17 +0000827 Method::kBitcastF32Arg,
Ben Clayton3a236c62022-05-28 05:28:11 +0000828};
829
Ben Clayton49a09142022-05-31 15:22:21 +0000830/// Methods that support abstract-integer materialization
Ben Clayton649d3d92022-05-31 18:11:34 +0000831/// Note: Doesn't contain kWorkgroupSize or kArrayLength as they have tighter constraints on the
832/// range of allowed integer values.
Ben Clayton49a09142022-05-31 15:22:21 +0000833constexpr Method kAIntMethods[] = {
834 Method::kSwitch,
835 Method::kIndex,
836};
837
Ben Clayton3a236c62022-05-28 05:28:11 +0000838/// Methods that support vector materialization
839constexpr Method kVectorMethods[] = {
840 Method::kLet,
841 Method::kVar,
842 Method::kBuiltinArg,
Ben Clayton8c7ffbd2022-05-28 07:09:17 +0000843 Method::kBitcastVec3F32Arg,
Ben Clayton3a236c62022-05-28 05:28:11 +0000844};
845
846/// Methods that support matrix materialization
847constexpr Method kMatrixMethods[] = {
848 Method::kLet,
849 Method::kVar,
850};
851
Ben Claytone34e0592022-05-25 21:16:55 +0000852INSTANTIATE_TEST_SUITE_P(
Ben Clayton3a236c62022-05-28 05:28:11 +0000853 MaterializeScalar,
854 MaterializeAbstractNumericToDefaultType,
855 testing::Combine(testing::Values(Expectation::kMaterialize),
856 testing::ValuesIn(kScalarMethods),
857 testing::ValuesIn(std::vector<Data>{
858 Types<i32, AInt>(0_a, 0.0), //
859 Types<i32, AInt>(1_a, 1.0), //
860 Types<i32, AInt>(-1_a, -1.0), //
861 Types<i32, AInt>(AInt(kHighestI32), kHighestI32), //
862 Types<i32, AInt>(AInt(kLowestI32), kLowestI32), //
863 Types<f32, AFloat>(0.0_a, 0.0), //
864 Types<f32, AFloat>(AFloat(kHighestF32), kHighestF32), //
865 Types<f32, AFloat>(AFloat(kLowestF32), kLowestF32), //
866 Types<f32, AFloat>(AFloat(kPiF32), kPiF64), //
867 Types<f32, AFloat>(AFloat(kSubnormalF32), kSubnormalF32), //
868 Types<f32, AFloat>(AFloat(-kSubnormalF32), -kSubnormalF32), //
869 })));
Ben Claytone34e0592022-05-25 21:16:55 +0000870
871INSTANTIATE_TEST_SUITE_P(
Ben Clayton3a236c62022-05-28 05:28:11 +0000872 MaterializeVector,
873 MaterializeAbstractNumericToDefaultType,
874 testing::Combine(testing::Values(Expectation::kMaterialize),
875 testing::ValuesIn(kVectorMethods),
876 testing::ValuesIn(std::vector<Data>{
877 Types<i32V, AIntV>(0_a, 0.0), //
878 Types<i32V, AIntV>(1_a, 1.0), //
879 Types<i32V, AIntV>(-1_a, -1.0), //
880 Types<i32V, AIntV>(AInt(kHighestI32), kHighestI32), //
881 Types<i32V, AIntV>(AInt(kLowestI32), kLowestI32), //
882 Types<f32V, AFloatV>(0.0_a, 0.0), //
883 Types<f32V, AFloatV>(1.0_a, 1.0), //
884 Types<f32V, AFloatV>(-1.0_a, -1.0), //
885 Types<f32V, AFloatV>(AFloat(kHighestF32), kHighestF32), //
886 Types<f32V, AFloatV>(AFloat(kLowestF32), kLowestF32), //
887 Types<f32V, AFloatV>(AFloat(kPiF32), kPiF64), //
888 Types<f32V, AFloatV>(AFloat(kSubnormalF32), kSubnormalF32), //
889 Types<f32V, AFloatV>(AFloat(-kSubnormalF32), -kSubnormalF32), //
890 })));
Ben Claytone34e0592022-05-25 21:16:55 +0000891
892INSTANTIATE_TEST_SUITE_P(
Ben Clayton3a236c62022-05-28 05:28:11 +0000893 MaterializeMatrix,
894 MaterializeAbstractNumericToDefaultType,
895 testing::Combine(testing::Values(Expectation::kMaterialize),
896 testing::ValuesIn(kMatrixMethods),
897 testing::ValuesIn(std::vector<Data>{
898 Types<f32M, AFloatM>(0.0_a, 0.0), //
899 Types<f32M, AFloatM>(1.0_a, 1.0), //
900 Types<f32M, AFloatM>(-1.0_a, -1.0), //
901 Types<f32M, AFloatM>(AFloat(kHighestF32), kHighestF32), //
902 Types<f32M, AFloatM>(AFloat(kLowestF32), kLowestF32), //
903 Types<f32M, AFloatM>(AFloat(kPiF32), kPiF64), //
904 Types<f32M, AFloatM>(AFloat(kSubnormalF32), kSubnormalF32), //
905 Types<f32M, AFloatM>(AFloat(-kSubnormalF32), -kSubnormalF32), //
906 })));
Ben Claytone34e0592022-05-25 21:16:55 +0000907
Ben Clayton49a09142022-05-31 15:22:21 +0000908INSTANTIATE_TEST_SUITE_P(MaterializeAInt,
Ben Clayton3a236c62022-05-28 05:28:11 +0000909 MaterializeAbstractNumericToDefaultType,
910 testing::Combine(testing::Values(Expectation::kMaterialize),
Ben Clayton49a09142022-05-31 15:22:21 +0000911 testing::ValuesIn(kAIntMethods),
Ben Clayton3a236c62022-05-28 05:28:11 +0000912 testing::ValuesIn(std::vector<Data>{
913 Types<i32, AInt>(0_a, 0.0), //
Ben Clayton49a09142022-05-31 15:22:21 +0000914 Types<i32, AInt>(10_a, 10.0), //
Ben Clayton3a236c62022-05-28 05:28:11 +0000915 Types<i32, AInt>(AInt(kHighestI32), kHighestI32), //
916 Types<i32, AInt>(AInt(kLowestI32), kLowestI32), //
917 })));
918
Ben Clayton649d3d92022-05-31 18:11:34 +0000919INSTANTIATE_TEST_SUITE_P(
920 MaterializeArrayLength,
921 MaterializeAbstractNumericToDefaultType,
922 testing::Combine(testing::Values(Expectation::kMaterialize),
923 testing::Values(Method::kArrayLength),
924 testing::ValuesIn(std::vector<Data>{
925 Types<i32, AInt>(1_a, 1.0), //
926 Types<i32, AInt>(10_a, 10.0), //
927 Types<i32, AInt>(1000_a, 1000.0), //
928 // Note: kHighestI32 cannot be used due to max-byte-size validation
929 })));
930
Ben Claytonb8ac93392022-05-28 10:34:06 +0000931INSTANTIATE_TEST_SUITE_P(MaterializeWorkgroupSize,
932 MaterializeAbstractNumericToDefaultType,
933 testing::Combine(testing::Values(Expectation::kMaterialize),
934 testing::Values(Method::kWorkgroupSize),
935 testing::ValuesIn(std::vector<Data>{
936 Types<i32, AInt>(1_a, 1.0), //
937 Types<i32, AInt>(10_a, 10.0), //
938 Types<i32, AInt>(65535_a, 65535.0), //
939 })));
940
Ben Clayton3a236c62022-05-28 05:28:11 +0000941INSTANTIATE_TEST_SUITE_P(ScalarValueCannotBeRepresented,
942 MaterializeAbstractNumericToDefaultType,
943 testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented),
944 testing::ValuesIn(kScalarMethods),
945 testing::ValuesIn(std::vector<Data>{
946 Types<i32, AInt>(0_a, kHighestI32 + 1), //
947 Types<i32, AInt>(0_a, kLowestI32 - 1), //
948 Types<f32, AFloat>(0.0_a, kTooBigF32), //
949 Types<f32, AFloat>(0.0_a, -kTooBigF32), //
950 })));
951
952INSTANTIATE_TEST_SUITE_P(VectorValueCannotBeRepresented,
953 MaterializeAbstractNumericToDefaultType,
954 testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented),
955 testing::ValuesIn(kVectorMethods),
956 testing::ValuesIn(std::vector<Data>{
957 Types<i32V, AIntV>(0_a, kHighestI32 + 1), //
958 Types<i32V, AIntV>(0_a, kLowestI32 - 1), //
959 Types<i32V, AIntV>(0_a, kHighestU32 + 1), //
960 Types<f32V, AFloatV>(0.0_a, kTooBigF32), //
961 Types<f32V, AFloatV>(0.0_a, -kTooBigF32), //
962 })));
963
964INSTANTIATE_TEST_SUITE_P(MatrixValueCannotBeRepresented,
965 MaterializeAbstractNumericToDefaultType,
966 testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented),
967 testing::ValuesIn(kMatrixMethods),
968 testing::ValuesIn(std::vector<Data>{
969 Types<f32M, AFloatM>(0.0_a, kTooBigF32), //
970 Types<f32M, AFloatM>(0.0_a, -kTooBigF32), //
971 })));
972
Ben Clayton49a09142022-05-31 15:22:21 +0000973INSTANTIATE_TEST_SUITE_P(AIntValueCannotBeRepresented,
Ben Clayton3a236c62022-05-28 05:28:11 +0000974 MaterializeAbstractNumericToDefaultType,
975 testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented),
Ben Clayton49a09142022-05-31 15:22:21 +0000976 testing::ValuesIn(kAIntMethods),
Ben Claytonb8ac93392022-05-28 10:34:06 +0000977 testing::ValuesIn(std::vector<Data>{
978 Types<i32, AInt>(0_a, kHighestI32 + 1), //
979 Types<i32, AInt>(0_a, kLowestI32 - 1), //
980 })));
981
982INSTANTIATE_TEST_SUITE_P(WorkgroupSizeValueCannotBeRepresented,
983 MaterializeAbstractNumericToDefaultType,
984 testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented),
985 testing::Values(Method::kWorkgroupSize),
Ben Clayton3a236c62022-05-28 05:28:11 +0000986 testing::ValuesIn(std::vector<Data>{
987 Types<i32, AInt>(0_a, kHighestI32 + 1), //
988 Types<i32, AInt>(0_a, kLowestI32 - 1), //
989 })));
990
Ben Clayton649d3d92022-05-31 18:11:34 +0000991INSTANTIATE_TEST_SUITE_P(ArrayLengthValueCannotBeRepresented,
992 MaterializeAbstractNumericToDefaultType,
993 testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented),
994 testing::Values(Method::kArrayLength),
995 testing::ValuesIn(std::vector<Data>{
996 Types<i32, AInt>(0_a, kHighestI32 + 1), //
997 })));
998
Ben Clayton3a236c62022-05-28 05:28:11 +0000999} // namespace materialize_abstract_numeric_to_default_type
Ben Clayton932418e2022-05-24 21:42:03 +00001000
Ben Clayton22d8dea2022-06-20 19:23:02 +00001001using MaterializeAbstractNumericToUnrelatedType = resolver::ResolverTest;
1002
1003TEST_F(MaterializeAbstractNumericToUnrelatedType, AIntToStructVarCtor) {
1004 Structure("S", {Member("a", ty.i32())});
1005 WrapInFunction(Decl(Var("v", ty.type_name("S"), Expr(Source{{12, 34}}, 1_a))));
1006 ASSERT_FALSE(r()->Resolve());
1007 EXPECT_THAT(
1008 r()->error(),
1009 testing::HasSubstr("error: cannot convert value of type 'abstract-int' to type 'S'"));
1010}
1011
1012TEST_F(MaterializeAbstractNumericToUnrelatedType, AIntToStructLetCtor) {
1013 Structure("S", {Member("a", ty.i32())});
1014 WrapInFunction(Decl(Let("v", ty.type_name("S"), Expr(Source{{12, 34}}, 1_a))));
1015 ASSERT_FALSE(r()->Resolve());
1016 EXPECT_THAT(
1017 r()->error(),
1018 testing::HasSubstr("error: cannot convert value of type 'abstract-int' to type 'S'"));
1019}
1020
Ben Clayton932418e2022-05-24 21:42:03 +00001021} // namespace
1022} // namespace tint::resolver