blob: 0e1b7d5a6d298bd0120957f86ee8e6f828711d4f [file] [log] [blame]
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001// Copyright 2021 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#ifndef SRC_TINT_RESOLVER_RESOLVER_TEST_HELPER_H_
16#define SRC_TINT_RESOLVER_RESOLVER_TEST_HELPER_H_
17
Ben Clayton6ae7c062022-05-25 20:31:54 +000018#include <functional>
Ryan Harrisondbc13af2022-02-21 15:19:07 +000019#include <memory>
Ben Clayton75bc93c2022-10-11 20:36:48 +000020#include <ostream>
Ryan Harrisondbc13af2022-02-21 15:19:07 +000021#include <string>
Antonio Maioranob6d524382022-08-31 22:59:08 +000022#include <tuple>
23#include <utility>
24#include <variant>
Ryan Harrisondbc13af2022-02-21 15:19:07 +000025
26#include "gtest/gtest.h"
27#include "src/tint/program_builder.h"
28#include "src/tint/resolver/resolver.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000029#include "src/tint/sem/statement.h"
Ben Clayton3fb9a3f2023-02-04 21:20:26 +000030#include "src/tint/sem/value_expression.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000031#include "src/tint/sem/variable.h"
Antonio Maiorano171c5422022-11-30 16:02:45 +000032#include "src/tint/traits.h"
dan sinclair094ace62022-12-08 15:33:01 +000033#include "src/tint/type/abstract_float.h"
34#include "src/tint/type/abstract_int.h"
Ben Clayton783b1692022-08-02 17:03:35 +000035#include "src/tint/utils/vector.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000036
dan sinclaird2093792022-04-07 17:45:45 +000037namespace tint::resolver {
Ryan Harrisondbc13af2022-02-21 15:19:07 +000038
39/// Helper class for testing
40class TestHelper : public ProgramBuilder {
dan sinclair41e4d9a2022-05-01 14:40:55 +000041 public:
42 /// Constructor
43 TestHelper();
Ryan Harrisondbc13af2022-02-21 15:19:07 +000044
dan sinclair41e4d9a2022-05-01 14:40:55 +000045 /// Destructor
46 ~TestHelper() override;
Ryan Harrisondbc13af2022-02-21 15:19:07 +000047
dan sinclair41e4d9a2022-05-01 14:40:55 +000048 /// @return a pointer to the Resolver
49 Resolver* r() const { return resolver_.get(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +000050
dan sinclair41e4d9a2022-05-01 14:40:55 +000051 /// @return a pointer to the validator
52 const Validator* v() const { return resolver_->GetValidatorForTesting(); }
dan sinclaird3a50802022-04-26 22:19:22 +000053
dan sinclair41e4d9a2022-05-01 14:40:55 +000054 /// Returns the statement that holds the given expression.
55 /// @param expr the ast::Expression
56 /// @return the ast::Statement of the ast::Expression, or nullptr if the
57 /// expression is not owned by a statement.
58 const ast::Statement* StmtOf(const ast::Expression* expr) {
59 auto* sem_stmt = Sem().Get(expr)->Stmt();
60 return sem_stmt ? sem_stmt->Declaration() : nullptr;
Ryan Harrisondbc13af2022-02-21 15:19:07 +000061 }
dan sinclair41e4d9a2022-05-01 14:40:55 +000062
63 /// Returns the BlockStatement that holds the given statement.
64 /// @param stmt the ast::Statement
65 /// @return the ast::BlockStatement that holds the ast::Statement, or nullptr
66 /// if the statement is not owned by a BlockStatement.
67 const ast::BlockStatement* BlockOf(const ast::Statement* stmt) {
68 auto* sem_stmt = Sem().Get(stmt);
69 return sem_stmt ? sem_stmt->Block()->Declaration() : nullptr;
Ryan Harrisondbc13af2022-02-21 15:19:07 +000070 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +000071
dan sinclair41e4d9a2022-05-01 14:40:55 +000072 /// Returns the BlockStatement that holds the given expression.
73 /// @param expr the ast::Expression
74 /// @return the ast::Statement of the ast::Expression, or nullptr if the
75 /// expression is not indirectly owned by a BlockStatement.
76 const ast::BlockStatement* BlockOf(const ast::Expression* expr) {
77 auto* sem_stmt = Sem().Get(expr)->Stmt();
78 return sem_stmt ? sem_stmt->Block()->Declaration() : nullptr;
79 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +000080
dan sinclair41e4d9a2022-05-01 14:40:55 +000081 /// Returns the semantic variable for the given identifier expression.
82 /// @param expr the identifier expression
83 /// @return the resolved sem::Variable of the identifier, or nullptr if
84 /// the expression did not resolve to a variable.
85 const sem::Variable* VarOf(const ast::Expression* expr) {
Ben Clayton0b4a2f12023-02-05 22:59:40 +000086 if (auto* sem = Sem().GetVal(expr)) {
87 if (auto* var_user = As<sem::VariableUser>(sem->UnwrapLoad())) {
88 return var_user->Variable();
89 }
90 }
91 return nullptr;
dan sinclair41e4d9a2022-05-01 14:40:55 +000092 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +000093
dan sinclair41e4d9a2022-05-01 14:40:55 +000094 /// Checks that all the users of the given variable are as expected
95 /// @param var the variable to check
96 /// @param expected_users the expected users of the variable
97 /// @return true if all users are as expected
98 bool CheckVarUsers(const ast::Variable* var,
Ben Clayton783b1692022-08-02 17:03:35 +000099 utils::VectorRef<const ast::Expression*> expected_users) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000100 auto& var_users = Sem().Get(var)->Users();
Ben Clayton783b1692022-08-02 17:03:35 +0000101 if (var_users.size() != expected_users.Length()) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000102 return false;
103 }
104 for (size_t i = 0; i < var_users.size(); i++) {
105 if (var_users[i]->Declaration() != expected_users[i]) {
106 return false;
107 }
108 }
109 return true;
110 }
111
112 /// @param type a type
113 /// @returns the name for `type` that closely resembles how it would be
114 /// declared in WGSL.
Ben Clayton971318f2023-02-14 13:52:43 +0000115 std::string FriendlyName(ast::Type type) { return Symbols().NameFor(type->identifier->symbol); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000116
117 /// @param type a type
118 /// @returns the name for `type` that closely resembles how it would be
119 /// declared in WGSL.
dan sinclair5f764d82022-12-08 00:32:27 +0000120 std::string FriendlyName(const type::Type* type) { return type->FriendlyName(Symbols()); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000121
122 private:
123 std::unique_ptr<Resolver> resolver_;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000124};
125
126class ResolverTest : public TestHelper, public testing::Test {};
127
128template <typename T>
dan sinclair41e4d9a2022-05-01 14:40:55 +0000129class ResolverTestWithParam : public TestHelper, public testing::TestWithParam<T> {};
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000130
131namespace builder {
132
Ben Clayton43919752022-03-07 17:05:28 +0000133template <uint32_t N, typename T>
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000134struct vec {};
135
136template <typename T>
137using vec2 = vec<2, T>;
138
139template <typename T>
140using vec3 = vec<3, T>;
141
142template <typename T>
143using vec4 = vec<4, T>;
144
Ben Clayton43919752022-03-07 17:05:28 +0000145template <uint32_t N, uint32_t M, typename T>
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000146struct mat {};
147
148template <typename T>
149using mat2x2 = mat<2, 2, T>;
150
151template <typename T>
152using mat2x3 = mat<2, 3, T>;
153
154template <typename T>
Ben Clayton0335c7d2022-12-14 11:55:58 +0000155using mat2x4 = mat<2, 4, T>;
156
157template <typename T>
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000158using mat3x2 = mat<3, 2, T>;
159
160template <typename T>
Ben Clayton0335c7d2022-12-14 11:55:58 +0000161using mat3x3 = mat<3, 3, T>;
162
163template <typename T>
164using mat3x4 = mat<3, 4, T>;
Antonio Maiorano9ba5f9e2022-11-23 23:12:56 +0000165
166template <typename T>
167using mat4x2 = mat<4, 2, T>;
168
169template <typename T>
Ben Clayton0335c7d2022-12-14 11:55:58 +0000170using mat4x3 = mat<4, 3, T>;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000171
172template <typename T>
173using mat4x4 = mat<4, 4, T>;
174
Ben Clayton43919752022-03-07 17:05:28 +0000175template <uint32_t N, typename T>
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000176struct array {};
177
178template <typename TO, int ID = 0>
179struct alias {};
180
181template <typename TO>
182using alias1 = alias<TO, 1>;
183
184template <typename TO>
185using alias2 = alias<TO, 2>;
186
187template <typename TO>
188using alias3 = alias<TO, 3>;
189
190template <typename TO>
191struct ptr {};
192
Ben Clayton95d174a2022-11-25 15:30:51 +0000193/// A scalar value
194using Scalar = std::variant<i32, u32, f32, f16, AInt, AFloat, bool>;
Antonio Maioranob6d524382022-08-31 22:59:08 +0000195
Antonio Maiorano29fb8f82022-10-17 16:11:02 +0000196/// Returns current variant value in `s` cast to type `T`
197template <typename T>
Antonio Maioranoffeae7a2022-11-25 23:35:53 +0000198T As(const Scalar& s) {
Antonio Maiorano29fb8f82022-10-17 16:11:02 +0000199 return std::visit([](auto&& v) { return static_cast<T>(v); }, s);
200}
201
Ben Clayton971318f2023-02-14 13:52:43 +0000202using ast_type_func_ptr = ast::Type (*)(ProgramBuilder& b);
Ben Clayton95d174a2022-11-25 15:30:51 +0000203using ast_expr_func_ptr = const ast::Expression* (*)(ProgramBuilder& b,
204 utils::VectorRef<Scalar> args);
Antonio Maioranob6d524382022-08-31 22:59:08 +0000205using ast_expr_from_double_func_ptr = const ast::Expression* (*)(ProgramBuilder& b, double v);
dan sinclair5f764d82022-12-08 00:32:27 +0000206using sem_type_func_ptr = const type::Type* (*)(ProgramBuilder& b);
Ben Clayton75bc93c2022-10-11 20:36:48 +0000207using type_name_func_ptr = std::string (*)();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000208
Antonio Maioranod4908672022-11-25 05:47:42 +0000209struct UnspecializedElementType {};
210
211/// Base template for DataType, specialized below.
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000212template <typename T>
Antonio Maioranod4908672022-11-25 05:47:42 +0000213struct DataType {
214 /// The element type
215 using ElementType = UnspecializedElementType;
216};
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000217
Ben Clayton23696b12022-05-18 21:56:28 +0000218/// Helper that represents no-type. Returns nullptr for all static methods.
219template <>
220struct DataType<void> {
Antonio Maioranod4908672022-11-25 05:47:42 +0000221 /// The element type
222 using ElementType = void;
223
Ben Clayton23696b12022-05-18 21:56:28 +0000224 /// @return nullptr
Ben Clayton971318f2023-02-14 13:52:43 +0000225 static inline ast::Type AST(ProgramBuilder&) { return {}; }
Ben Clayton23696b12022-05-18 21:56:28 +0000226 /// @return nullptr
dan sinclair5f764d82022-12-08 00:32:27 +0000227 static inline const type::Type* Sem(ProgramBuilder&) { return nullptr; }
Ben Clayton23696b12022-05-18 21:56:28 +0000228};
229
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000230/// Helper for building bool types and expressions
231template <>
232struct DataType<bool> {
Ben Claytona8d52282022-05-25 21:07:04 +0000233 /// The element type
234 using ElementType = bool;
235
dan sinclair41e4d9a2022-05-01 14:40:55 +0000236 /// false as bool is not a composite type
237 static constexpr bool is_composite = false;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000238
dan sinclair41e4d9a2022-05-01 14:40:55 +0000239 /// @param b the ProgramBuilder
240 /// @return a new AST bool type
Ben Clayton971318f2023-02-14 13:52:43 +0000241 static inline ast::Type AST(ProgramBuilder& b) { return b.ty.bool_(); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000242 /// @param b the ProgramBuilder
243 /// @return the semantic bool type
dan sinclaird37ecf92022-12-08 16:39:59 +0000244 static inline const type::Type* Sem(ProgramBuilder& b) { return b.create<type::Bool>(); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000245 /// @param b the ProgramBuilder
Antonio Maioranob6d524382022-08-31 22:59:08 +0000246 /// @param args args of size 1 with the boolean value to init with
dan sinclair41e4d9a2022-05-01 14:40:55 +0000247 /// @return a new AST expression of the bool type
Ben Clayton95d174a2022-11-25 15:30:51 +0000248 static inline const ast::Expression* Expr(ProgramBuilder& b, utils::VectorRef<Scalar> args) {
249 return b.Expr(std::get<bool>(args[0]));
Antonio Maioranob6d524382022-08-31 22:59:08 +0000250 }
251 /// @param b the ProgramBuilder
252 /// @param v arg of type double that will be cast to bool.
253 /// @return a new AST expression of the bool type
254 static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
Ben Clayton95d174a2022-11-25 15:30:51 +0000255 return Expr(b, utils::Vector<Scalar, 1>{static_cast<ElementType>(v)});
dan sinclair41e4d9a2022-05-01 14:40:55 +0000256 }
Ben Claytona2ce4ec2022-05-20 12:11:00 +0000257 /// @returns the WGSL name for the type
258 static inline std::string Name() { return "bool"; }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000259};
260
261/// Helper for building i32 types and expressions
262template <>
263struct DataType<i32> {
Ben Claytona8d52282022-05-25 21:07:04 +0000264 /// The element type
265 using ElementType = i32;
266
dan sinclair41e4d9a2022-05-01 14:40:55 +0000267 /// false as i32 is not a composite type
268 static constexpr bool is_composite = false;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000269
dan sinclair41e4d9a2022-05-01 14:40:55 +0000270 /// @param b the ProgramBuilder
271 /// @return a new AST i32 type
Ben Clayton971318f2023-02-14 13:52:43 +0000272 static inline ast::Type AST(ProgramBuilder& b) { return b.ty.i32(); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000273 /// @param b the ProgramBuilder
274 /// @return the semantic i32 type
dan sinclaird37ecf92022-12-08 16:39:59 +0000275 static inline const type::Type* Sem(ProgramBuilder& b) { return b.create<type::I32>(); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000276 /// @param b the ProgramBuilder
Antonio Maioranob6d524382022-08-31 22:59:08 +0000277 /// @param args args of size 1 with the i32 value to init with
dan sinclair41e4d9a2022-05-01 14:40:55 +0000278 /// @return a new AST i32 literal value expression
Ben Clayton95d174a2022-11-25 15:30:51 +0000279 static inline const ast::Expression* Expr(ProgramBuilder& b, utils::VectorRef<Scalar> args) {
280 return b.Expr(std::get<i32>(args[0]));
Antonio Maioranob6d524382022-08-31 22:59:08 +0000281 }
282 /// @param b the ProgramBuilder
283 /// @param v arg of type double that will be cast to i32.
284 /// @return a new AST i32 literal value expression
285 static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
Ben Clayton95d174a2022-11-25 15:30:51 +0000286 return Expr(b, utils::Vector<Scalar, 1>{static_cast<ElementType>(v)});
dan sinclair41e4d9a2022-05-01 14:40:55 +0000287 }
Ben Claytona2ce4ec2022-05-20 12:11:00 +0000288 /// @returns the WGSL name for the type
289 static inline std::string Name() { return "i32"; }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000290};
291
292/// Helper for building u32 types and expressions
293template <>
294struct DataType<u32> {
Ben Claytona8d52282022-05-25 21:07:04 +0000295 /// The element type
296 using ElementType = u32;
297
dan sinclair41e4d9a2022-05-01 14:40:55 +0000298 /// false as u32 is not a composite type
299 static constexpr bool is_composite = false;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000300
dan sinclair41e4d9a2022-05-01 14:40:55 +0000301 /// @param b the ProgramBuilder
302 /// @return a new AST u32 type
Ben Clayton971318f2023-02-14 13:52:43 +0000303 static inline ast::Type AST(ProgramBuilder& b) { return b.ty.u32(); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000304 /// @param b the ProgramBuilder
305 /// @return the semantic u32 type
dan sinclaird37ecf92022-12-08 16:39:59 +0000306 static inline const type::Type* Sem(ProgramBuilder& b) { return b.create<type::U32>(); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000307 /// @param b the ProgramBuilder
Antonio Maioranob6d524382022-08-31 22:59:08 +0000308 /// @param args args of size 1 with the u32 value to init with
dan sinclair41e4d9a2022-05-01 14:40:55 +0000309 /// @return a new AST u32 literal value expression
Ben Clayton95d174a2022-11-25 15:30:51 +0000310 static inline const ast::Expression* Expr(ProgramBuilder& b, utils::VectorRef<Scalar> args) {
311 return b.Expr(std::get<u32>(args[0]));
Antonio Maioranob6d524382022-08-31 22:59:08 +0000312 }
313 /// @param b the ProgramBuilder
314 /// @param v arg of type double that will be cast to u32.
315 /// @return a new AST u32 literal value expression
316 static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
Ben Clayton95d174a2022-11-25 15:30:51 +0000317 return Expr(b, utils::Vector<Scalar, 1>{static_cast<ElementType>(v)});
dan sinclair41e4d9a2022-05-01 14:40:55 +0000318 }
Ben Claytona2ce4ec2022-05-20 12:11:00 +0000319 /// @returns the WGSL name for the type
320 static inline std::string Name() { return "u32"; }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000321};
322
323/// Helper for building f32 types and expressions
324template <>
325struct DataType<f32> {
Ben Claytona8d52282022-05-25 21:07:04 +0000326 /// The element type
327 using ElementType = f32;
328
dan sinclair41e4d9a2022-05-01 14:40:55 +0000329 /// false as f32 is not a composite type
330 static constexpr bool is_composite = false;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000331
dan sinclair41e4d9a2022-05-01 14:40:55 +0000332 /// @param b the ProgramBuilder
333 /// @return a new AST f32 type
Ben Clayton971318f2023-02-14 13:52:43 +0000334 static inline ast::Type AST(ProgramBuilder& b) { return b.ty.f32(); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000335 /// @param b the ProgramBuilder
336 /// @return the semantic f32 type
dan sinclaird37ecf92022-12-08 16:39:59 +0000337 static inline const type::Type* Sem(ProgramBuilder& b) { return b.create<type::F32>(); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000338 /// @param b the ProgramBuilder
Antonio Maioranob6d524382022-08-31 22:59:08 +0000339 /// @param args args of size 1 with the f32 value to init with
dan sinclair41e4d9a2022-05-01 14:40:55 +0000340 /// @return a new AST f32 literal value expression
Ben Clayton95d174a2022-11-25 15:30:51 +0000341 static inline const ast::Expression* Expr(ProgramBuilder& b, utils::VectorRef<Scalar> args) {
342 return b.Expr(std::get<f32>(args[0]));
Antonio Maioranob6d524382022-08-31 22:59:08 +0000343 }
344 /// @param b the ProgramBuilder
345 /// @param v arg of type double that will be cast to f32.
346 /// @return a new AST f32 literal value expression
347 static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
Ben Clayton95d174a2022-11-25 15:30:51 +0000348 return Expr(b, utils::Vector<Scalar, 1>{static_cast<f32>(v)});
dan sinclair41e4d9a2022-05-01 14:40:55 +0000349 }
Ben Claytona2ce4ec2022-05-20 12:11:00 +0000350 /// @returns the WGSL name for the type
351 static inline std::string Name() { return "f32"; }
352};
353
354/// Helper for building f16 types and expressions
355template <>
356struct DataType<f16> {
Ben Claytona8d52282022-05-25 21:07:04 +0000357 /// The element type
358 using ElementType = f16;
359
Ben Claytona2ce4ec2022-05-20 12:11:00 +0000360 /// false as f16 is not a composite type
361 static constexpr bool is_composite = false;
362
363 /// @param b the ProgramBuilder
364 /// @return a new AST f16 type
Ben Clayton971318f2023-02-14 13:52:43 +0000365 static inline ast::Type AST(ProgramBuilder& b) { return b.ty.f16(); }
Ben Claytona2ce4ec2022-05-20 12:11:00 +0000366 /// @param b the ProgramBuilder
367 /// @return the semantic f16 type
dan sinclaird37ecf92022-12-08 16:39:59 +0000368 static inline const type::Type* Sem(ProgramBuilder& b) { return b.create<type::F16>(); }
Ben Claytona2ce4ec2022-05-20 12:11:00 +0000369 /// @param b the ProgramBuilder
Antonio Maioranob6d524382022-08-31 22:59:08 +0000370 /// @param args args of size 1 with the f16 value to init with
Ben Claytona2ce4ec2022-05-20 12:11:00 +0000371 /// @return a new AST f16 literal value expression
Ben Clayton95d174a2022-11-25 15:30:51 +0000372 static inline const ast::Expression* Expr(ProgramBuilder& b, utils::VectorRef<Scalar> args) {
373 return b.Expr(std::get<f16>(args[0]));
Antonio Maioranob6d524382022-08-31 22:59:08 +0000374 }
375 /// @param b the ProgramBuilder
376 /// @param v arg of type double that will be cast to f16.
377 /// @return a new AST f16 literal value expression
378 static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
Ben Clayton95d174a2022-11-25 15:30:51 +0000379 return Expr(b, utils::Vector<Scalar, 1>{static_cast<ElementType>(v)});
Ben Claytona2ce4ec2022-05-20 12:11:00 +0000380 }
381 /// @returns the WGSL name for the type
382 static inline std::string Name() { return "f16"; }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000383};
384
Ben Clayton23696b12022-05-18 21:56:28 +0000385/// Helper for building abstract float types and expressions
386template <>
387struct DataType<AFloat> {
Ben Claytona8d52282022-05-25 21:07:04 +0000388 /// The element type
389 using ElementType = AFloat;
390
Ben Clayton23696b12022-05-18 21:56:28 +0000391 /// false as AFloat is not a composite type
392 static constexpr bool is_composite = false;
393
Ben Claytona2ce4ec2022-05-20 12:11:00 +0000394 /// @returns nullptr, as abstract floats are un-typeable
Ben Clayton971318f2023-02-14 13:52:43 +0000395 static inline ast::Type AST(ProgramBuilder&) { return {}; }
Ben Clayton23696b12022-05-18 21:56:28 +0000396 /// @param b the ProgramBuilder
397 /// @return the semantic abstract-float type
dan sinclair5f764d82022-12-08 00:32:27 +0000398 static inline const type::Type* Sem(ProgramBuilder& b) {
dan sinclair094ace62022-12-08 15:33:01 +0000399 return b.create<type::AbstractFloat>();
dan sinclair5f764d82022-12-08 00:32:27 +0000400 }
Ben Clayton23696b12022-05-18 21:56:28 +0000401 /// @param b the ProgramBuilder
Antonio Maioranob6d524382022-08-31 22:59:08 +0000402 /// @param args args of size 1 with the abstract-float value to init with
Ben Clayton23696b12022-05-18 21:56:28 +0000403 /// @return a new AST abstract-float literal value expression
Ben Clayton95d174a2022-11-25 15:30:51 +0000404 static inline const ast::Expression* Expr(ProgramBuilder& b, utils::VectorRef<Scalar> args) {
405 return b.Expr(std::get<AFloat>(args[0]));
Antonio Maioranob6d524382022-08-31 22:59:08 +0000406 }
407 /// @param b the ProgramBuilder
408 /// @param v arg of type double that will be cast to AFloat.
409 /// @return a new AST abstract-float literal value expression
410 static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
Ben Clayton95d174a2022-11-25 15:30:51 +0000411 return Expr(b, utils::Vector<Scalar, 1>{static_cast<ElementType>(v)});
Ben Clayton23696b12022-05-18 21:56:28 +0000412 }
Ben Claytona2ce4ec2022-05-20 12:11:00 +0000413 /// @returns the WGSL name for the type
414 static inline std::string Name() { return "abstract-float"; }
Ben Clayton23696b12022-05-18 21:56:28 +0000415};
416
417/// Helper for building abstract integer types and expressions
418template <>
419struct DataType<AInt> {
Ben Claytona8d52282022-05-25 21:07:04 +0000420 /// The element type
421 using ElementType = AInt;
422
Ben Clayton23696b12022-05-18 21:56:28 +0000423 /// false as AFloat is not a composite type
424 static constexpr bool is_composite = false;
425
Ben Claytona2ce4ec2022-05-20 12:11:00 +0000426 /// @returns nullptr, as abstract integers are un-typeable
Ben Clayton971318f2023-02-14 13:52:43 +0000427 static inline ast::Type AST(ProgramBuilder&) { return {}; }
Ben Clayton23696b12022-05-18 21:56:28 +0000428 /// @param b the ProgramBuilder
429 /// @return the semantic abstract-int type
dan sinclair094ace62022-12-08 15:33:01 +0000430 static inline const type::Type* Sem(ProgramBuilder& b) { return b.create<type::AbstractInt>(); }
Ben Clayton23696b12022-05-18 21:56:28 +0000431 /// @param b the ProgramBuilder
Antonio Maioranob6d524382022-08-31 22:59:08 +0000432 /// @param args args of size 1 with the abstract-int value to init with
Ben Clayton23696b12022-05-18 21:56:28 +0000433 /// @return a new AST abstract-int literal value expression
Ben Clayton95d174a2022-11-25 15:30:51 +0000434 static inline const ast::Expression* Expr(ProgramBuilder& b, utils::VectorRef<Scalar> args) {
435 return b.Expr(std::get<AInt>(args[0]));
Antonio Maioranob6d524382022-08-31 22:59:08 +0000436 }
437 /// @param b the ProgramBuilder
438 /// @param v arg of type double that will be cast to AInt.
439 /// @return a new AST abstract-int literal value expression
440 static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
Ben Clayton95d174a2022-11-25 15:30:51 +0000441 return Expr(b, utils::Vector<Scalar, 1>{static_cast<ElementType>(v)});
Ben Clayton23696b12022-05-18 21:56:28 +0000442 }
Ben Claytona2ce4ec2022-05-20 12:11:00 +0000443 /// @returns the WGSL name for the type
444 static inline std::string Name() { return "abstract-int"; }
Ben Clayton23696b12022-05-18 21:56:28 +0000445};
446
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000447/// Helper for building vector types and expressions
Ben Clayton43919752022-03-07 17:05:28 +0000448template <uint32_t N, typename T>
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000449struct DataType<vec<N, T>> {
Ben Claytona8d52282022-05-25 21:07:04 +0000450 /// The element type
451 using ElementType = T;
452
dan sinclair41e4d9a2022-05-01 14:40:55 +0000453 /// true as vectors are a composite type
454 static constexpr bool is_composite = true;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000455
dan sinclair41e4d9a2022-05-01 14:40:55 +0000456 /// @param b the ProgramBuilder
457 /// @return a new AST vector type
Ben Clayton971318f2023-02-14 13:52:43 +0000458 static inline ast::Type AST(ProgramBuilder& b) {
459 if (IsInferOrAbstract<T>) {
460 return b.ty.vec<Infer, N>();
461 } else {
462 return b.ty.vec(DataType<T>::AST(b), N);
463 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000464 }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000465 /// @param b the ProgramBuilder
466 /// @return the semantic vector type
dan sinclair5f764d82022-12-08 00:32:27 +0000467 static inline const type::Type* Sem(ProgramBuilder& b) {
dan sinclair0e780da2022-12-08 22:21:24 +0000468 return b.create<type::Vector>(DataType<T>::Sem(b), N);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000469 }
470 /// @param b the ProgramBuilder
Antonio Maioranob6d524382022-08-31 22:59:08 +0000471 /// @param args args of size 1 or N with values of type T to initialize with
dan sinclair41e4d9a2022-05-01 14:40:55 +0000472 /// @return a new AST vector value expression
Ben Clayton95d174a2022-11-25 15:30:51 +0000473 static inline const ast::Expression* Expr(ProgramBuilder& b, utils::VectorRef<Scalar> args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +0000474 return b.Call(AST(b), ExprArgs(b, std::move(args)));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000475 }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000476 /// @param b the ProgramBuilder
Antonio Maioranob6d524382022-08-31 22:59:08 +0000477 /// @param args args of size 1 or N with values of type T to initialize with
dan sinclair41e4d9a2022-05-01 14:40:55 +0000478 /// @return the list of expressions that are used to construct the vector
Ben Clayton95d174a2022-11-25 15:30:51 +0000479 static inline auto ExprArgs(ProgramBuilder& b, utils::VectorRef<Scalar> args) {
480 const bool one_value = args.Length() == 1;
Antonio Maioranob6d524382022-08-31 22:59:08 +0000481 utils::Vector<const ast::Expression*, N> r;
482 for (size_t i = 0; i < N; ++i) {
Ben Clayton95d174a2022-11-25 15:30:51 +0000483 r.Push(DataType<T>::Expr(b, utils::Vector<Scalar, 1>{one_value ? args[0] : args[i]}));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000484 }
Antonio Maioranob6d524382022-08-31 22:59:08 +0000485 return r;
486 }
487 /// @param b the ProgramBuilder
488 /// @param v arg of type double that will be cast to ElementType
489 /// @return a new AST vector value expression
490 static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
Ben Clayton95d174a2022-11-25 15:30:51 +0000491 return Expr(b, utils::Vector<Scalar, 1>{static_cast<ElementType>(v)});
dan sinclair41e4d9a2022-05-01 14:40:55 +0000492 }
Ben Claytona2ce4ec2022-05-20 12:11:00 +0000493 /// @returns the WGSL name for the type
494 static inline std::string Name() {
495 return "vec" + std::to_string(N) + "<" + DataType<T>::Name() + ">";
496 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000497};
498
499/// Helper for building matrix types and expressions
Ben Clayton43919752022-03-07 17:05:28 +0000500template <uint32_t N, uint32_t M, typename T>
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000501struct DataType<mat<N, M, T>> {
Ben Claytona8d52282022-05-25 21:07:04 +0000502 /// The element type
503 using ElementType = T;
504
dan sinclair41e4d9a2022-05-01 14:40:55 +0000505 /// true as matrices are a composite type
506 static constexpr bool is_composite = true;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000507
dan sinclair41e4d9a2022-05-01 14:40:55 +0000508 /// @param b the ProgramBuilder
509 /// @return a new AST matrix type
Ben Clayton971318f2023-02-14 13:52:43 +0000510 static inline ast::Type AST(ProgramBuilder& b) {
511 if (IsInferOrAbstract<T>) {
512 return b.ty.mat<Infer, N, M>();
513 } else {
514 return b.ty.mat(DataType<T>::AST(b), N, M);
515 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000516 }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000517 /// @param b the ProgramBuilder
518 /// @return the semantic matrix type
dan sinclair5f764d82022-12-08 00:32:27 +0000519 static inline const type::Type* Sem(ProgramBuilder& b) {
dan sinclair0e780da2022-12-08 22:21:24 +0000520 auto* column_type = b.create<type::Vector>(DataType<T>::Sem(b), M);
521 return b.create<type::Matrix>(column_type, N);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000522 }
523 /// @param b the ProgramBuilder
Antonio Maioranob6d524382022-08-31 22:59:08 +0000524 /// @param args args of size 1 or N*M with values of type T to initialize with
dan sinclair41e4d9a2022-05-01 14:40:55 +0000525 /// @return a new AST matrix value expression
Ben Clayton95d174a2022-11-25 15:30:51 +0000526 static inline const ast::Expression* Expr(ProgramBuilder& b, utils::VectorRef<Scalar> args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +0000527 return b.Call(AST(b), ExprArgs(b, std::move(args)));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000528 }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000529 /// @param b the ProgramBuilder
Antonio Maioranob6d524382022-08-31 22:59:08 +0000530 /// @param args args of size 1 or N*M with values of type T to initialize with
531 /// @return a new AST matrix value expression
Ben Clayton95d174a2022-11-25 15:30:51 +0000532 static inline auto ExprArgs(ProgramBuilder& b, utils::VectorRef<Scalar> args) {
533 const bool one_value = args.Length() == 1;
Antonio Maioranob6d524382022-08-31 22:59:08 +0000534 size_t next = 0;
535 utils::Vector<const ast::Expression*, N> r;
536 for (uint32_t i = 0; i < N; ++i) {
537 if (one_value) {
Ben Clayton95d174a2022-11-25 15:30:51 +0000538 r.Push(DataType<vec<M, T>>::Expr(b, utils::Vector<Scalar, 1>{args[0]}));
Antonio Maioranob6d524382022-08-31 22:59:08 +0000539 } else {
Ben Clayton95d174a2022-11-25 15:30:51 +0000540 utils::Vector<Scalar, M> v;
Antonio Maioranob6d524382022-08-31 22:59:08 +0000541 for (size_t j = 0; j < M; ++j) {
Ben Clayton95d174a2022-11-25 15:30:51 +0000542 v.Push(args[next++]);
Antonio Maioranob6d524382022-08-31 22:59:08 +0000543 }
Ben Clayton95d174a2022-11-25 15:30:51 +0000544 r.Push(DataType<vec<M, T>>::Expr(b, std::move(v)));
Antonio Maioranob6d524382022-08-31 22:59:08 +0000545 }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000546 }
Antonio Maioranob6d524382022-08-31 22:59:08 +0000547 return r;
548 }
549 /// @param b the ProgramBuilder
550 /// @param v arg of type double that will be cast to ElementType
551 /// @return a new AST matrix value expression
552 static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
Ben Clayton95d174a2022-11-25 15:30:51 +0000553 return Expr(b, utils::Vector<Scalar, 1>{static_cast<ElementType>(v)});
dan sinclair41e4d9a2022-05-01 14:40:55 +0000554 }
Ben Claytona2ce4ec2022-05-20 12:11:00 +0000555 /// @returns the WGSL name for the type
556 static inline std::string Name() {
557 return "mat" + std::to_string(N) + "x" + std::to_string(M) + "<" + DataType<T>::Name() +
558 ">";
559 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000560};
561
562/// Helper for building alias types and expressions
563template <typename T, int ID>
564struct DataType<alias<T, ID>> {
Ben Claytona8d52282022-05-25 21:07:04 +0000565 /// The element type
Antonio Maioranob6d524382022-08-31 22:59:08 +0000566 using ElementType = typename DataType<T>::ElementType;
Ben Claytona8d52282022-05-25 21:07:04 +0000567
dan sinclair41e4d9a2022-05-01 14:40:55 +0000568 /// true if the aliased type is a composite type
569 static constexpr bool is_composite = DataType<T>::is_composite;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000570
dan sinclair41e4d9a2022-05-01 14:40:55 +0000571 /// @param b the ProgramBuilder
572 /// @return a new AST alias type
Ben Clayton971318f2023-02-14 13:52:43 +0000573 static inline ast::Type AST(ProgramBuilder& b) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000574 auto name = b.Symbols().Register("alias_" + std::to_string(ID));
575 if (!b.AST().LookupType(name)) {
Ben Clayton971318f2023-02-14 13:52:43 +0000576 auto type = DataType<T>::AST(b);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000577 b.AST().AddTypeDecl(b.ty.alias(name, type));
578 }
Ben Clayton2117f802023-02-03 14:01:43 +0000579 return b.ty(name);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000580 }
Ben Clayton971318f2023-02-14 13:52:43 +0000581
dan sinclair41e4d9a2022-05-01 14:40:55 +0000582 /// @param b the ProgramBuilder
583 /// @return the semantic aliased type
dan sinclair5f764d82022-12-08 00:32:27 +0000584 static inline const type::Type* Sem(ProgramBuilder& b) { return DataType<T>::Sem(b); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000585
dan sinclair41e4d9a2022-05-01 14:40:55 +0000586 /// @param b the ProgramBuilder
Antonio Maioranob6d524382022-08-31 22:59:08 +0000587 /// @param args the value nested elements will be initialized with
dan sinclair41e4d9a2022-05-01 14:40:55 +0000588 /// @return a new AST expression of the alias type
589 template <bool IS_COMPOSITE = is_composite>
Ben Clayton95d174a2022-11-25 15:30:51 +0000590 static inline traits::EnableIf<!IS_COMPOSITE, const ast::Expression*> Expr(
591 ProgramBuilder& b,
592 utils::VectorRef<Scalar> args) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000593 // Cast
Ben Clayton01ac21c2023-02-07 16:14:25 +0000594 return b.Call(AST(b), DataType<T>::Expr(b, std::move(args)));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000595 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000596
dan sinclair41e4d9a2022-05-01 14:40:55 +0000597 /// @param b the ProgramBuilder
Antonio Maioranob6d524382022-08-31 22:59:08 +0000598 /// @param args the value nested elements will be initialized with
dan sinclair41e4d9a2022-05-01 14:40:55 +0000599 /// @return a new AST expression of the alias type
600 template <bool IS_COMPOSITE = is_composite>
Ben Clayton95d174a2022-11-25 15:30:51 +0000601 static inline traits::EnableIf<IS_COMPOSITE, const ast::Expression*> Expr(
602 ProgramBuilder& b,
603 utils::VectorRef<Scalar> args) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000604 // Construct
Ben Clayton01ac21c2023-02-07 16:14:25 +0000605 return b.Call(AST(b), DataType<T>::ExprArgs(b, std::move(args)));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000606 }
Antonio Maioranob6d524382022-08-31 22:59:08 +0000607
608 /// @param b the ProgramBuilder
609 /// @param v arg of type double that will be cast to ElementType
610 /// @return a new AST expression of the alias type
611 static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
Ben Clayton95d174a2022-11-25 15:30:51 +0000612 return Expr(b, utils::Vector<Scalar, 1>{static_cast<ElementType>(v)});
Antonio Maioranob6d524382022-08-31 22:59:08 +0000613 }
614
Ben Claytona2ce4ec2022-05-20 12:11:00 +0000615 /// @returns the WGSL name for the type
616 static inline std::string Name() { return "alias_" + std::to_string(ID); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000617};
618
619/// Helper for building pointer types and expressions
620template <typename T>
621struct DataType<ptr<T>> {
Ben Claytona8d52282022-05-25 21:07:04 +0000622 /// The element type
Antonio Maioranob6d524382022-08-31 22:59:08 +0000623 using ElementType = typename DataType<T>::ElementType;
Ben Claytona8d52282022-05-25 21:07:04 +0000624
dan sinclair41e4d9a2022-05-01 14:40:55 +0000625 /// true if the pointer type is a composite type
626 static constexpr bool is_composite = false;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000627
dan sinclair41e4d9a2022-05-01 14:40:55 +0000628 /// @param b the ProgramBuilder
629 /// @return a new AST alias type
Ben Clayton971318f2023-02-14 13:52:43 +0000630 static inline ast::Type AST(ProgramBuilder& b) {
dan sinclair2a651632023-02-19 04:03:55 +0000631 return b.ty.pointer(DataType<T>::AST(b), builtin::AddressSpace::kPrivate,
dan sinclairb6cc4cb2023-02-19 04:01:29 +0000632 builtin::Access::kUndefined);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000633 }
634 /// @param b the ProgramBuilder
635 /// @return the semantic aliased type
dan sinclair5f764d82022-12-08 00:32:27 +0000636 static inline const type::Type* Sem(ProgramBuilder& b) {
dan sinclair2a651632023-02-19 04:03:55 +0000637 return b.create<type::Pointer>(DataType<T>::Sem(b), builtin::AddressSpace::kPrivate,
dan sinclairb6cc4cb2023-02-19 04:01:29 +0000638 builtin::Access::kReadWrite);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000639 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000640
dan sinclair41e4d9a2022-05-01 14:40:55 +0000641 /// @param b the ProgramBuilder
Antonio Maioranob6d524382022-08-31 22:59:08 +0000642 /// @return a new AST expression of the pointer type
Ben Clayton95d174a2022-11-25 15:30:51 +0000643 static inline const ast::Expression* Expr(ProgramBuilder& b,
644 utils::VectorRef<Scalar> /*unused*/) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000645 auto sym = b.Symbols().New("global_for_ptr");
dan sinclair2a651632023-02-19 04:03:55 +0000646 b.GlobalVar(sym, DataType<T>::AST(b), builtin::AddressSpace::kPrivate);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000647 return b.AddressOf(sym);
648 }
Antonio Maioranob6d524382022-08-31 22:59:08 +0000649
650 /// @param b the ProgramBuilder
651 /// @param v arg of type double that will be cast to ElementType
652 /// @return a new AST expression of the pointer type
653 static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
Ben Clayton95d174a2022-11-25 15:30:51 +0000654 return Expr(b, utils::Vector<Scalar, 1>{static_cast<ElementType>(v)});
Antonio Maioranob6d524382022-08-31 22:59:08 +0000655 }
656
Ben Claytona2ce4ec2022-05-20 12:11:00 +0000657 /// @returns the WGSL name for the type
658 static inline std::string Name() { return "ptr<" + DataType<T>::Name() + ">"; }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000659};
660
661/// Helper for building array types and expressions
Ben Clayton43919752022-03-07 17:05:28 +0000662template <uint32_t N, typename T>
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000663struct DataType<array<N, T>> {
Ben Claytona8d52282022-05-25 21:07:04 +0000664 /// The element type
Antonio Maioranob6d524382022-08-31 22:59:08 +0000665 using ElementType = typename DataType<T>::ElementType;
Ben Claytona8d52282022-05-25 21:07:04 +0000666
dan sinclair41e4d9a2022-05-01 14:40:55 +0000667 /// true as arrays are a composite type
668 static constexpr bool is_composite = true;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000669
dan sinclair41e4d9a2022-05-01 14:40:55 +0000670 /// @param b the ProgramBuilder
671 /// @return a new AST array type
Ben Clayton971318f2023-02-14 13:52:43 +0000672 static inline ast::Type AST(ProgramBuilder& b) {
673 if (auto ast = DataType<T>::AST(b)) {
Ben Clayton4a656202022-08-01 17:36:54 +0000674 return b.ty.array(ast, u32(N));
675 }
Ben Clayton971318f2023-02-14 13:52:43 +0000676 return b.ty.array<Infer>();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000677 }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000678 /// @param b the ProgramBuilder
679 /// @return the semantic array type
dan sinclair5f764d82022-12-08 00:32:27 +0000680 static inline const type::Type* Sem(ProgramBuilder& b) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000681 auto* el = DataType<T>::Sem(b);
dan sinclair5f764d82022-12-08 00:32:27 +0000682 const type::ArrayCount* count = nullptr;
dan sinclair78f80672022-09-22 22:28:21 +0000683 if (N == 0) {
dan sinclair5f764d82022-12-08 00:32:27 +0000684 count = b.create<type::RuntimeArrayCount>();
dan sinclair4b1d79e2022-12-01 23:45:18 +0000685 } else {
dan sinclair5f764d82022-12-08 00:32:27 +0000686 count = b.create<type::ConstantArrayCount>(N);
dan sinclair78f80672022-09-22 22:28:21 +0000687 }
dan sinclair946858a2022-12-08 22:21:24 +0000688 return b.create<type::Array>(
dan sinclair41e4d9a2022-05-01 14:40:55 +0000689 /* element */ el,
dan sinclair78f80672022-09-22 22:28:21 +0000690 /* count */ count,
dan sinclair41e4d9a2022-05-01 14:40:55 +0000691 /* align */ el->Align(),
Ben Clayton4a656202022-08-01 17:36:54 +0000692 /* size */ N * el->Size(),
dan sinclair41e4d9a2022-05-01 14:40:55 +0000693 /* stride */ el->Align(),
694 /* implicit_stride */ el->Align());
695 }
696 /// @param b the ProgramBuilder
Antonio Maioranob6d524382022-08-31 22:59:08 +0000697 /// @param args args of size 1 or N with values of type T to initialize with
dan sinclair41e4d9a2022-05-01 14:40:55 +0000698 /// with
699 /// @return a new AST array value expression
Ben Clayton95d174a2022-11-25 15:30:51 +0000700 static inline const ast::Expression* Expr(ProgramBuilder& b, utils::VectorRef<Scalar> args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +0000701 return b.Call(AST(b), ExprArgs(b, std::move(args)));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000702 }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000703 /// @param b the ProgramBuilder
Antonio Maioranob6d524382022-08-31 22:59:08 +0000704 /// @param args args of size 1 or N with values of type T to initialize with
dan sinclair41e4d9a2022-05-01 14:40:55 +0000705 /// @return the list of expressions that are used to construct the array
Ben Clayton95d174a2022-11-25 15:30:51 +0000706 static inline auto ExprArgs(ProgramBuilder& b, utils::VectorRef<Scalar> args) {
707 const bool one_value = args.Length() == 1;
Antonio Maioranob6d524382022-08-31 22:59:08 +0000708 utils::Vector<const ast::Expression*, N> r;
dan sinclair41e4d9a2022-05-01 14:40:55 +0000709 for (uint32_t i = 0; i < N; i++) {
Ben Clayton95d174a2022-11-25 15:30:51 +0000710 r.Push(DataType<T>::Expr(b, utils::Vector<Scalar, 1>{one_value ? args[0] : args[i]}));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000711 }
Antonio Maioranob6d524382022-08-31 22:59:08 +0000712 return r;
713 }
714 /// @param b the ProgramBuilder
715 /// @param v arg of type double that will be cast to ElementType
716 /// @return a new AST array value expression
717 static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
Ben Clayton95d174a2022-11-25 15:30:51 +0000718 return Expr(b, utils::Vector<Scalar, 1>{static_cast<ElementType>(v)});
dan sinclair41e4d9a2022-05-01 14:40:55 +0000719 }
Ben Claytona2ce4ec2022-05-20 12:11:00 +0000720 /// @returns the WGSL name for the type
721 static inline std::string Name() {
722 return "array<" + DataType<T>::Name() + ", " + std::to_string(N) + ">";
723 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000724};
725
726/// Struct of all creation pointer types
727struct CreatePtrs {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000728 /// ast node type create function
729 ast_type_func_ptr ast;
730 /// ast expression type create function
731 ast_expr_func_ptr expr;
Antonio Maioranob6d524382022-08-31 22:59:08 +0000732 /// ast expression type create function from double arg
733 ast_expr_from_double_func_ptr expr_from_double;
dan sinclair41e4d9a2022-05-01 14:40:55 +0000734 /// sem type create function
735 sem_type_func_ptr sem;
Ben Clayton75bc93c2022-10-11 20:36:48 +0000736 /// type name function
737 type_name_func_ptr name;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000738};
739
Ben Clayton75bc93c2022-10-11 20:36:48 +0000740/// @param o the std::ostream to write to
741/// @param ptrs the CreatePtrs
742/// @return the std::ostream so calls can be chained
743inline std::ostream& operator<<(std::ostream& o, const CreatePtrs& ptrs) {
744 return o << (ptrs.name ? ptrs.name() : "<unknown>");
745}
746
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000747/// Returns a CreatePtrs struct instance with all creation pointer types for
748/// type `T`
749template <typename T>
750constexpr CreatePtrs CreatePtrsFor() {
Ben Clayton75bc93c2022-10-11 20:36:48 +0000751 return {DataType<T>::AST, DataType<T>::Expr, DataType<T>::ExprFromDouble, DataType<T>::Sem,
752 DataType<T>::Name};
Antonio Maioranob6d524382022-08-31 22:59:08 +0000753}
754
Antonio Maioranod4908672022-11-25 05:47:42 +0000755/// True if DataType<T> is specialized for T, false otherwise.
756template <typename T>
757const bool IsDataTypeSpecializedFor =
758 !std::is_same_v<typename DataType<T>::ElementType, UnspecializedElementType>;
759
Ben Clayton95d174a2022-11-25 15:30:51 +0000760/// Value is used to create Values with a Scalar vector initializer.
761struct Value {
762 /// Creates a Value for type T initialized with `args`
Antonio Maioranod4908672022-11-25 05:47:42 +0000763 /// @param args the scalar args
Ben Clayton95d174a2022-11-25 15:30:51 +0000764 /// @returns Value
765 template <typename T>
766 static Value Create(utils::VectorRef<Scalar> args) {
767 static_assert(IsDataTypeSpecializedFor<T>, "No DataType<T> specialization exists");
768 using EL_TY = typename builder::DataType<T>::ElementType;
769 return Value{
Antonio Maiorano05661852022-12-20 18:34:06 +0000770 std::move(args), //
771 CreatePtrsFor<T>(), //
772 tint::IsAbstract<EL_TY>, //
773 tint::IsIntegral<EL_TY>, //
774 tint::FriendlyName<EL_TY>(),
Ben Clayton95d174a2022-11-25 15:30:51 +0000775 };
Antonio Maiorano29fb8f82022-10-17 16:11:02 +0000776 }
Antonio Maioranob6d524382022-08-31 22:59:08 +0000777
Ben Clayton95d174a2022-11-25 15:30:51 +0000778 /// Creates an `ast::Expression` for the type T passing in previously stored args
779 /// @param b the ProgramBuilder
780 /// @returns an expression node
Antonio Maiorano05661852022-12-20 18:34:06 +0000781 const ast::Expression* Expr(ProgramBuilder& b) const { return (*create_ptrs.expr)(b, args); }
Antonio Maiorano29fb8f82022-10-17 16:11:02 +0000782
783 /// Prints this value to the output stream
784 /// @param o the output stream
785 /// @returns input argument `o`
Ben Clayton95d174a2022-11-25 15:30:51 +0000786 std::ostream& Print(std::ostream& o) const {
787 o << type_name << "(";
788 for (auto& a : args) {
789 std::visit([&](auto& v) { o << v; }, a);
790 if (&a != &args.Back()) {
Antonio Maiorano29fb8f82022-10-17 16:11:02 +0000791 o << ", ";
792 }
793 }
794 o << ")";
795 return o;
796 }
797
Ben Clayton95d174a2022-11-25 15:30:51 +0000798 /// The arguments used to construct the value
799 utils::Vector<Scalar, 4> args;
Antonio Maiorano05661852022-12-20 18:34:06 +0000800 /// CreatePtrs for value's type used to create an expression with `args`
801 builder::CreatePtrs create_ptrs;
Ben Clayton95d174a2022-11-25 15:30:51 +0000802 /// True if the element type is abstract
803 bool is_abstract = false;
804 /// True if the element type is an integer
805 bool is_integral = false;
806 /// The name of the type.
807 const char* type_name = "<invalid>";
Antonio Maioranod4908672022-11-25 05:47:42 +0000808};
809
810/// Prints Value to ostream
811inline std::ostream& operator<<(std::ostream& o, const Value& value) {
812 return value.Print(o);
Antonio Maiorano29aa6132022-09-07 19:34:44 +0000813}
814
Antonio Maioranod4908672022-11-25 05:47:42 +0000815/// True if T is Value, false otherwise
Antonio Maioranob6d524382022-08-31 22:59:08 +0000816template <typename T>
Antonio Maioranod4908672022-11-25 05:47:42 +0000817constexpr bool IsValue = std::is_same_v<T, Value>;
818
819/// Creates a Value of DataType<T> from a scalar `v`
820template <typename T>
821Value Val(T v) {
Antonio Maiorano171c5422022-11-30 16:02:45 +0000822 static_assert(traits::IsTypeIn<T, Scalar>, "v must be a Number of bool");
Ben Clayton95d174a2022-11-25 15:30:51 +0000823 return Value::Create<T>(utils::Vector<Scalar, 1>{v});
Antonio Maioranob6d524382022-08-31 22:59:08 +0000824}
825
Antonio Maioranod4908672022-11-25 05:47:42 +0000826/// Creates a Value of DataType<vec<N, T>> from N scalar `args`
Antonio Maiorano05661852022-12-20 18:34:06 +0000827template <typename... Ts>
828Value Vec(Ts... args) {
829 using FirstT = std::tuple_element_t<0, std::tuple<Ts...>>;
Antonio Maioranoc73d6732022-12-23 21:09:10 +0000830 static_assert(sizeof...(args) >= 2 && sizeof...(args) <= 4, "Invalid vector size");
Antonio Maiorano05661852022-12-20 18:34:06 +0000831 static_assert(std::conjunction_v<std::is_same<FirstT, Ts>...>,
832 "Vector args must all be the same type");
Antonio Maioranod4908672022-11-25 05:47:42 +0000833 constexpr size_t N = sizeof...(args);
Ben Clayton95d174a2022-11-25 15:30:51 +0000834 utils::Vector<Scalar, sizeof...(args)> v{args...};
835 return Value::Create<vec<N, FirstT>>(std::move(v));
Antonio Maioranob6d524382022-08-31 22:59:08 +0000836}
837
Antonio Maiorano6b4622f2022-12-22 16:27:43 +0000838/// Creates a Value of DataType<array<N, T>> from N scalar `args`
839template <typename... Ts>
840Value Array(Ts... args) {
841 using FirstT = std::tuple_element_t<0, std::tuple<Ts...>>;
842 static_assert(std::conjunction_v<std::is_same<FirstT, Ts>...>,
843 "Array args must all be the same type");
844 constexpr size_t N = sizeof...(args);
845 utils::Vector<Scalar, sizeof...(args)> v{args...};
846 return Value::Create<array<N, FirstT>>(std::move(v));
847}
848
Antonio Maioranod4908672022-11-25 05:47:42 +0000849/// Creates a Value of DataType<mat<C,R,T> from C*R scalar `args`
Antonio Maioranob6d524382022-08-31 22:59:08 +0000850template <size_t C, size_t R, typename T>
Antonio Maioranod4908672022-11-25 05:47:42 +0000851Value Mat(const T (&m_in)[C][R]) {
Ben Clayton95d174a2022-11-25 15:30:51 +0000852 utils::Vector<Scalar, C * R> m;
Antonio Maioranob6d524382022-08-31 22:59:08 +0000853 for (uint32_t i = 0; i < C; ++i) {
854 for (size_t j = 0; j < R; ++j) {
855 m.Push(m_in[i][j]);
856 }
857 }
Ben Clayton95d174a2022-11-25 15:30:51 +0000858 return Value::Create<mat<C, R, T>>(std::move(m));
Antonio Maioranob6d524382022-08-31 22:59:08 +0000859}
860
Antonio Maioranod4908672022-11-25 05:47:42 +0000861/// Creates a Value of DataType<mat<2,R,T> from column vectors `c0` and `c1`
Antonio Maioranob6d524382022-08-31 22:59:08 +0000862template <typename T, size_t R>
Antonio Maioranod4908672022-11-25 05:47:42 +0000863Value Mat(const T (&c0)[R], const T (&c1)[R]) {
Antonio Maioranob6d524382022-08-31 22:59:08 +0000864 constexpr size_t C = 2;
Ben Clayton95d174a2022-11-25 15:30:51 +0000865 utils::Vector<Scalar, C * R> m;
Antonio Maioranob6d524382022-08-31 22:59:08 +0000866 for (auto v : c0) {
867 m.Push(v);
868 }
869 for (auto v : c1) {
870 m.Push(v);
871 }
Ben Clayton95d174a2022-11-25 15:30:51 +0000872 return Value::Create<mat<C, R, T>>(std::move(m));
Antonio Maioranob6d524382022-08-31 22:59:08 +0000873}
874
Antonio Maioranod4908672022-11-25 05:47:42 +0000875/// Creates a Value of DataType<mat<3,R,T> from column vectors `c0`, `c1`, and `c2`
Antonio Maioranob6d524382022-08-31 22:59:08 +0000876template <typename T, size_t R>
Antonio Maioranod4908672022-11-25 05:47:42 +0000877Value Mat(const T (&c0)[R], const T (&c1)[R], const T (&c2)[R]) {
Antonio Maioranob6d524382022-08-31 22:59:08 +0000878 constexpr size_t C = 3;
Ben Clayton95d174a2022-11-25 15:30:51 +0000879 utils::Vector<Scalar, C * R> m;
Antonio Maioranob6d524382022-08-31 22:59:08 +0000880 for (auto v : c0) {
881 m.Push(v);
882 }
883 for (auto v : c1) {
884 m.Push(v);
885 }
886 for (auto v : c2) {
887 m.Push(v);
888 }
Ben Clayton95d174a2022-11-25 15:30:51 +0000889 return Value::Create<mat<C, R, T>>(std::move(m));
Antonio Maioranob6d524382022-08-31 22:59:08 +0000890}
891
Antonio Maioranod4908672022-11-25 05:47:42 +0000892/// Creates a Value of DataType<mat<4,R,T> from column vectors `c0`, `c1`, `c2`, and `c3`
Antonio Maioranob6d524382022-08-31 22:59:08 +0000893template <typename T, size_t R>
Antonio Maioranod4908672022-11-25 05:47:42 +0000894Value Mat(const T (&c0)[R], const T (&c1)[R], const T (&c2)[R], const T (&c3)[R]) {
Antonio Maioranob6d524382022-08-31 22:59:08 +0000895 constexpr size_t C = 4;
Ben Clayton95d174a2022-11-25 15:30:51 +0000896 utils::Vector<Scalar, C * R> m;
Antonio Maioranob6d524382022-08-31 22:59:08 +0000897 for (auto v : c0) {
898 m.Push(v);
899 }
900 for (auto v : c1) {
901 m.Push(v);
902 }
903 for (auto v : c2) {
904 m.Push(v);
905 }
906 for (auto v : c3) {
907 m.Push(v);
908 }
Ben Clayton95d174a2022-11-25 15:30:51 +0000909 return Value::Create<mat<C, R, T>>(std::move(m));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000910}
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000911} // namespace builder
dan sinclaird2093792022-04-07 17:45:45 +0000912} // namespace tint::resolver
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000913
914#endif // SRC_TINT_RESOLVER_RESOLVER_TEST_HELPER_H_