Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 1 | // 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 Clayton | 6ae7c06 | 2022-05-25 20:31:54 +0000 | [diff] [blame] | 18 | #include <functional> |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 19 | #include <memory> |
Ben Clayton | 75bc93c | 2022-10-11 20:36:48 +0000 | [diff] [blame] | 20 | #include <ostream> |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 21 | #include <string> |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 22 | #include <tuple> |
| 23 | #include <utility> |
| 24 | #include <variant> |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 25 | |
| 26 | #include "gtest/gtest.h" |
| 27 | #include "src/tint/program_builder.h" |
| 28 | #include "src/tint/resolver/resolver.h" |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 29 | #include "src/tint/sem/statement.h" |
Ben Clayton | 3fb9a3f | 2023-02-04 21:20:26 +0000 | [diff] [blame] | 30 | #include "src/tint/sem/value_expression.h" |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 31 | #include "src/tint/sem/variable.h" |
Antonio Maiorano | 171c542 | 2022-11-30 16:02:45 +0000 | [diff] [blame] | 32 | #include "src/tint/traits.h" |
dan sinclair | 094ace6 | 2022-12-08 15:33:01 +0000 | [diff] [blame] | 33 | #include "src/tint/type/abstract_float.h" |
| 34 | #include "src/tint/type/abstract_int.h" |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 35 | #include "src/tint/utils/vector.h" |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 36 | |
dan sinclair | d209379 | 2022-04-07 17:45:45 +0000 | [diff] [blame] | 37 | namespace tint::resolver { |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 38 | |
| 39 | /// Helper class for testing |
| 40 | class TestHelper : public ProgramBuilder { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 41 | public: |
| 42 | /// Constructor |
| 43 | TestHelper(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 44 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 45 | /// Destructor |
| 46 | ~TestHelper() override; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 47 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 48 | /// @return a pointer to the Resolver |
| 49 | Resolver* r() const { return resolver_.get(); } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 50 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 51 | /// @return a pointer to the validator |
| 52 | const Validator* v() const { return resolver_->GetValidatorForTesting(); } |
dan sinclair | d3a5080 | 2022-04-26 22:19:22 +0000 | [diff] [blame] | 53 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 54 | /// 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 Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 61 | } |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 62 | |
| 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 Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 70 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 71 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 72 | /// 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 Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 80 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 81 | /// 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 Clayton | 0b4a2f1 | 2023-02-05 22:59:40 +0000 | [diff] [blame] | 86 | 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 sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 92 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 93 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 94 | /// 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 Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 99 | utils::VectorRef<const ast::Expression*> expected_users) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 100 | auto& var_users = Sem().Get(var)->Users(); |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 101 | if (var_users.size() != expected_users.Length()) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 102 | 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 Clayton | 971318f | 2023-02-14 13:52:43 +0000 | [diff] [blame] | 115 | std::string FriendlyName(ast::Type type) { return Symbols().NameFor(type->identifier->symbol); } |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 116 | |
| 117 | /// @param type a type |
| 118 | /// @returns the name for `type` that closely resembles how it would be |
| 119 | /// declared in WGSL. |
dan sinclair | 5f764d8 | 2022-12-08 00:32:27 +0000 | [diff] [blame] | 120 | std::string FriendlyName(const type::Type* type) { return type->FriendlyName(Symbols()); } |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 121 | |
| 122 | private: |
| 123 | std::unique_ptr<Resolver> resolver_; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 124 | }; |
| 125 | |
| 126 | class ResolverTest : public TestHelper, public testing::Test {}; |
| 127 | |
| 128 | template <typename T> |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 129 | class ResolverTestWithParam : public TestHelper, public testing::TestWithParam<T> {}; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 130 | |
| 131 | namespace builder { |
| 132 | |
Ben Clayton | 4391975 | 2022-03-07 17:05:28 +0000 | [diff] [blame] | 133 | template <uint32_t N, typename T> |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 134 | struct vec {}; |
| 135 | |
| 136 | template <typename T> |
| 137 | using vec2 = vec<2, T>; |
| 138 | |
| 139 | template <typename T> |
| 140 | using vec3 = vec<3, T>; |
| 141 | |
| 142 | template <typename T> |
| 143 | using vec4 = vec<4, T>; |
| 144 | |
Ben Clayton | 4391975 | 2022-03-07 17:05:28 +0000 | [diff] [blame] | 145 | template <uint32_t N, uint32_t M, typename T> |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 146 | struct mat {}; |
| 147 | |
| 148 | template <typename T> |
| 149 | using mat2x2 = mat<2, 2, T>; |
| 150 | |
| 151 | template <typename T> |
| 152 | using mat2x3 = mat<2, 3, T>; |
| 153 | |
| 154 | template <typename T> |
Ben Clayton | 0335c7d | 2022-12-14 11:55:58 +0000 | [diff] [blame] | 155 | using mat2x4 = mat<2, 4, T>; |
| 156 | |
| 157 | template <typename T> |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 158 | using mat3x2 = mat<3, 2, T>; |
| 159 | |
| 160 | template <typename T> |
Ben Clayton | 0335c7d | 2022-12-14 11:55:58 +0000 | [diff] [blame] | 161 | using mat3x3 = mat<3, 3, T>; |
| 162 | |
| 163 | template <typename T> |
| 164 | using mat3x4 = mat<3, 4, T>; |
Antonio Maiorano | 9ba5f9e | 2022-11-23 23:12:56 +0000 | [diff] [blame] | 165 | |
| 166 | template <typename T> |
| 167 | using mat4x2 = mat<4, 2, T>; |
| 168 | |
| 169 | template <typename T> |
Ben Clayton | 0335c7d | 2022-12-14 11:55:58 +0000 | [diff] [blame] | 170 | using mat4x3 = mat<4, 3, T>; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 171 | |
| 172 | template <typename T> |
| 173 | using mat4x4 = mat<4, 4, T>; |
| 174 | |
Ben Clayton | 4391975 | 2022-03-07 17:05:28 +0000 | [diff] [blame] | 175 | template <uint32_t N, typename T> |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 176 | struct array {}; |
| 177 | |
| 178 | template <typename TO, int ID = 0> |
| 179 | struct alias {}; |
| 180 | |
| 181 | template <typename TO> |
| 182 | using alias1 = alias<TO, 1>; |
| 183 | |
| 184 | template <typename TO> |
| 185 | using alias2 = alias<TO, 2>; |
| 186 | |
| 187 | template <typename TO> |
| 188 | using alias3 = alias<TO, 3>; |
| 189 | |
| 190 | template <typename TO> |
| 191 | struct ptr {}; |
| 192 | |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 193 | /// A scalar value |
| 194 | using Scalar = std::variant<i32, u32, f32, f16, AInt, AFloat, bool>; |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 195 | |
Antonio Maiorano | 29fb8f8 | 2022-10-17 16:11:02 +0000 | [diff] [blame] | 196 | /// Returns current variant value in `s` cast to type `T` |
| 197 | template <typename T> |
Antonio Maiorano | ffeae7a | 2022-11-25 23:35:53 +0000 | [diff] [blame] | 198 | T As(const Scalar& s) { |
Antonio Maiorano | 29fb8f8 | 2022-10-17 16:11:02 +0000 | [diff] [blame] | 199 | return std::visit([](auto&& v) { return static_cast<T>(v); }, s); |
| 200 | } |
| 201 | |
Ben Clayton | 971318f | 2023-02-14 13:52:43 +0000 | [diff] [blame] | 202 | using ast_type_func_ptr = ast::Type (*)(ProgramBuilder& b); |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 203 | using ast_expr_func_ptr = const ast::Expression* (*)(ProgramBuilder& b, |
| 204 | utils::VectorRef<Scalar> args); |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 205 | using ast_expr_from_double_func_ptr = const ast::Expression* (*)(ProgramBuilder& b, double v); |
dan sinclair | 5f764d8 | 2022-12-08 00:32:27 +0000 | [diff] [blame] | 206 | using sem_type_func_ptr = const type::Type* (*)(ProgramBuilder& b); |
Ben Clayton | 75bc93c | 2022-10-11 20:36:48 +0000 | [diff] [blame] | 207 | using type_name_func_ptr = std::string (*)(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 208 | |
Antonio Maiorano | d490867 | 2022-11-25 05:47:42 +0000 | [diff] [blame] | 209 | struct UnspecializedElementType {}; |
| 210 | |
| 211 | /// Base template for DataType, specialized below. |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 212 | template <typename T> |
Antonio Maiorano | d490867 | 2022-11-25 05:47:42 +0000 | [diff] [blame] | 213 | struct DataType { |
| 214 | /// The element type |
| 215 | using ElementType = UnspecializedElementType; |
| 216 | }; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 217 | |
Ben Clayton | 23696b1 | 2022-05-18 21:56:28 +0000 | [diff] [blame] | 218 | /// Helper that represents no-type. Returns nullptr for all static methods. |
| 219 | template <> |
| 220 | struct DataType<void> { |
Antonio Maiorano | d490867 | 2022-11-25 05:47:42 +0000 | [diff] [blame] | 221 | /// The element type |
| 222 | using ElementType = void; |
| 223 | |
Ben Clayton | 23696b1 | 2022-05-18 21:56:28 +0000 | [diff] [blame] | 224 | /// @return nullptr |
Ben Clayton | 971318f | 2023-02-14 13:52:43 +0000 | [diff] [blame] | 225 | static inline ast::Type AST(ProgramBuilder&) { return {}; } |
Ben Clayton | 23696b1 | 2022-05-18 21:56:28 +0000 | [diff] [blame] | 226 | /// @return nullptr |
dan sinclair | 5f764d8 | 2022-12-08 00:32:27 +0000 | [diff] [blame] | 227 | static inline const type::Type* Sem(ProgramBuilder&) { return nullptr; } |
Ben Clayton | 23696b1 | 2022-05-18 21:56:28 +0000 | [diff] [blame] | 228 | }; |
| 229 | |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 230 | /// Helper for building bool types and expressions |
| 231 | template <> |
| 232 | struct DataType<bool> { |
Ben Clayton | a8d5228 | 2022-05-25 21:07:04 +0000 | [diff] [blame] | 233 | /// The element type |
| 234 | using ElementType = bool; |
| 235 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 236 | /// false as bool is not a composite type |
| 237 | static constexpr bool is_composite = false; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 238 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 239 | /// @param b the ProgramBuilder |
| 240 | /// @return a new AST bool type |
Ben Clayton | 971318f | 2023-02-14 13:52:43 +0000 | [diff] [blame] | 241 | static inline ast::Type AST(ProgramBuilder& b) { return b.ty.bool_(); } |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 242 | /// @param b the ProgramBuilder |
| 243 | /// @return the semantic bool type |
dan sinclair | d37ecf9 | 2022-12-08 16:39:59 +0000 | [diff] [blame] | 244 | static inline const type::Type* Sem(ProgramBuilder& b) { return b.create<type::Bool>(); } |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 245 | /// @param b the ProgramBuilder |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 246 | /// @param args args of size 1 with the boolean value to init with |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 247 | /// @return a new AST expression of the bool type |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 248 | static inline const ast::Expression* Expr(ProgramBuilder& b, utils::VectorRef<Scalar> args) { |
| 249 | return b.Expr(std::get<bool>(args[0])); |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 250 | } |
| 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 Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 255 | return Expr(b, utils::Vector<Scalar, 1>{static_cast<ElementType>(v)}); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 256 | } |
Ben Clayton | a2ce4ec | 2022-05-20 12:11:00 +0000 | [diff] [blame] | 257 | /// @returns the WGSL name for the type |
| 258 | static inline std::string Name() { return "bool"; } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 259 | }; |
| 260 | |
| 261 | /// Helper for building i32 types and expressions |
| 262 | template <> |
| 263 | struct DataType<i32> { |
Ben Clayton | a8d5228 | 2022-05-25 21:07:04 +0000 | [diff] [blame] | 264 | /// The element type |
| 265 | using ElementType = i32; |
| 266 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 267 | /// false as i32 is not a composite type |
| 268 | static constexpr bool is_composite = false; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 269 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 270 | /// @param b the ProgramBuilder |
| 271 | /// @return a new AST i32 type |
Ben Clayton | 971318f | 2023-02-14 13:52:43 +0000 | [diff] [blame] | 272 | static inline ast::Type AST(ProgramBuilder& b) { return b.ty.i32(); } |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 273 | /// @param b the ProgramBuilder |
| 274 | /// @return the semantic i32 type |
dan sinclair | d37ecf9 | 2022-12-08 16:39:59 +0000 | [diff] [blame] | 275 | static inline const type::Type* Sem(ProgramBuilder& b) { return b.create<type::I32>(); } |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 276 | /// @param b the ProgramBuilder |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 277 | /// @param args args of size 1 with the i32 value to init with |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 278 | /// @return a new AST i32 literal value expression |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 279 | static inline const ast::Expression* Expr(ProgramBuilder& b, utils::VectorRef<Scalar> args) { |
| 280 | return b.Expr(std::get<i32>(args[0])); |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 281 | } |
| 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 Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 286 | return Expr(b, utils::Vector<Scalar, 1>{static_cast<ElementType>(v)}); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 287 | } |
Ben Clayton | a2ce4ec | 2022-05-20 12:11:00 +0000 | [diff] [blame] | 288 | /// @returns the WGSL name for the type |
| 289 | static inline std::string Name() { return "i32"; } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 290 | }; |
| 291 | |
| 292 | /// Helper for building u32 types and expressions |
| 293 | template <> |
| 294 | struct DataType<u32> { |
Ben Clayton | a8d5228 | 2022-05-25 21:07:04 +0000 | [diff] [blame] | 295 | /// The element type |
| 296 | using ElementType = u32; |
| 297 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 298 | /// false as u32 is not a composite type |
| 299 | static constexpr bool is_composite = false; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 300 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 301 | /// @param b the ProgramBuilder |
| 302 | /// @return a new AST u32 type |
Ben Clayton | 971318f | 2023-02-14 13:52:43 +0000 | [diff] [blame] | 303 | static inline ast::Type AST(ProgramBuilder& b) { return b.ty.u32(); } |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 304 | /// @param b the ProgramBuilder |
| 305 | /// @return the semantic u32 type |
dan sinclair | d37ecf9 | 2022-12-08 16:39:59 +0000 | [diff] [blame] | 306 | static inline const type::Type* Sem(ProgramBuilder& b) { return b.create<type::U32>(); } |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 307 | /// @param b the ProgramBuilder |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 308 | /// @param args args of size 1 with the u32 value to init with |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 309 | /// @return a new AST u32 literal value expression |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 310 | static inline const ast::Expression* Expr(ProgramBuilder& b, utils::VectorRef<Scalar> args) { |
| 311 | return b.Expr(std::get<u32>(args[0])); |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 312 | } |
| 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 Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 317 | return Expr(b, utils::Vector<Scalar, 1>{static_cast<ElementType>(v)}); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 318 | } |
Ben Clayton | a2ce4ec | 2022-05-20 12:11:00 +0000 | [diff] [blame] | 319 | /// @returns the WGSL name for the type |
| 320 | static inline std::string Name() { return "u32"; } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 321 | }; |
| 322 | |
| 323 | /// Helper for building f32 types and expressions |
| 324 | template <> |
| 325 | struct DataType<f32> { |
Ben Clayton | a8d5228 | 2022-05-25 21:07:04 +0000 | [diff] [blame] | 326 | /// The element type |
| 327 | using ElementType = f32; |
| 328 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 329 | /// false as f32 is not a composite type |
| 330 | static constexpr bool is_composite = false; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 331 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 332 | /// @param b the ProgramBuilder |
| 333 | /// @return a new AST f32 type |
Ben Clayton | 971318f | 2023-02-14 13:52:43 +0000 | [diff] [blame] | 334 | static inline ast::Type AST(ProgramBuilder& b) { return b.ty.f32(); } |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 335 | /// @param b the ProgramBuilder |
| 336 | /// @return the semantic f32 type |
dan sinclair | d37ecf9 | 2022-12-08 16:39:59 +0000 | [diff] [blame] | 337 | static inline const type::Type* Sem(ProgramBuilder& b) { return b.create<type::F32>(); } |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 338 | /// @param b the ProgramBuilder |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 339 | /// @param args args of size 1 with the f32 value to init with |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 340 | /// @return a new AST f32 literal value expression |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 341 | static inline const ast::Expression* Expr(ProgramBuilder& b, utils::VectorRef<Scalar> args) { |
| 342 | return b.Expr(std::get<f32>(args[0])); |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 343 | } |
| 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 Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 348 | return Expr(b, utils::Vector<Scalar, 1>{static_cast<f32>(v)}); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 349 | } |
Ben Clayton | a2ce4ec | 2022-05-20 12:11:00 +0000 | [diff] [blame] | 350 | /// @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 |
| 355 | template <> |
| 356 | struct DataType<f16> { |
Ben Clayton | a8d5228 | 2022-05-25 21:07:04 +0000 | [diff] [blame] | 357 | /// The element type |
| 358 | using ElementType = f16; |
| 359 | |
Ben Clayton | a2ce4ec | 2022-05-20 12:11:00 +0000 | [diff] [blame] | 360 | /// 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 Clayton | 971318f | 2023-02-14 13:52:43 +0000 | [diff] [blame] | 365 | static inline ast::Type AST(ProgramBuilder& b) { return b.ty.f16(); } |
Ben Clayton | a2ce4ec | 2022-05-20 12:11:00 +0000 | [diff] [blame] | 366 | /// @param b the ProgramBuilder |
| 367 | /// @return the semantic f16 type |
dan sinclair | d37ecf9 | 2022-12-08 16:39:59 +0000 | [diff] [blame] | 368 | static inline const type::Type* Sem(ProgramBuilder& b) { return b.create<type::F16>(); } |
Ben Clayton | a2ce4ec | 2022-05-20 12:11:00 +0000 | [diff] [blame] | 369 | /// @param b the ProgramBuilder |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 370 | /// @param args args of size 1 with the f16 value to init with |
Ben Clayton | a2ce4ec | 2022-05-20 12:11:00 +0000 | [diff] [blame] | 371 | /// @return a new AST f16 literal value expression |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 372 | static inline const ast::Expression* Expr(ProgramBuilder& b, utils::VectorRef<Scalar> args) { |
| 373 | return b.Expr(std::get<f16>(args[0])); |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 374 | } |
| 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 Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 379 | return Expr(b, utils::Vector<Scalar, 1>{static_cast<ElementType>(v)}); |
Ben Clayton | a2ce4ec | 2022-05-20 12:11:00 +0000 | [diff] [blame] | 380 | } |
| 381 | /// @returns the WGSL name for the type |
| 382 | static inline std::string Name() { return "f16"; } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 383 | }; |
| 384 | |
Ben Clayton | 23696b1 | 2022-05-18 21:56:28 +0000 | [diff] [blame] | 385 | /// Helper for building abstract float types and expressions |
| 386 | template <> |
| 387 | struct DataType<AFloat> { |
Ben Clayton | a8d5228 | 2022-05-25 21:07:04 +0000 | [diff] [blame] | 388 | /// The element type |
| 389 | using ElementType = AFloat; |
| 390 | |
Ben Clayton | 23696b1 | 2022-05-18 21:56:28 +0000 | [diff] [blame] | 391 | /// false as AFloat is not a composite type |
| 392 | static constexpr bool is_composite = false; |
| 393 | |
Ben Clayton | a2ce4ec | 2022-05-20 12:11:00 +0000 | [diff] [blame] | 394 | /// @returns nullptr, as abstract floats are un-typeable |
Ben Clayton | 971318f | 2023-02-14 13:52:43 +0000 | [diff] [blame] | 395 | static inline ast::Type AST(ProgramBuilder&) { return {}; } |
Ben Clayton | 23696b1 | 2022-05-18 21:56:28 +0000 | [diff] [blame] | 396 | /// @param b the ProgramBuilder |
| 397 | /// @return the semantic abstract-float type |
dan sinclair | 5f764d8 | 2022-12-08 00:32:27 +0000 | [diff] [blame] | 398 | static inline const type::Type* Sem(ProgramBuilder& b) { |
dan sinclair | 094ace6 | 2022-12-08 15:33:01 +0000 | [diff] [blame] | 399 | return b.create<type::AbstractFloat>(); |
dan sinclair | 5f764d8 | 2022-12-08 00:32:27 +0000 | [diff] [blame] | 400 | } |
Ben Clayton | 23696b1 | 2022-05-18 21:56:28 +0000 | [diff] [blame] | 401 | /// @param b the ProgramBuilder |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 402 | /// @param args args of size 1 with the abstract-float value to init with |
Ben Clayton | 23696b1 | 2022-05-18 21:56:28 +0000 | [diff] [blame] | 403 | /// @return a new AST abstract-float literal value expression |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 404 | static inline const ast::Expression* Expr(ProgramBuilder& b, utils::VectorRef<Scalar> args) { |
| 405 | return b.Expr(std::get<AFloat>(args[0])); |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 406 | } |
| 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 Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 411 | return Expr(b, utils::Vector<Scalar, 1>{static_cast<ElementType>(v)}); |
Ben Clayton | 23696b1 | 2022-05-18 21:56:28 +0000 | [diff] [blame] | 412 | } |
Ben Clayton | a2ce4ec | 2022-05-20 12:11:00 +0000 | [diff] [blame] | 413 | /// @returns the WGSL name for the type |
| 414 | static inline std::string Name() { return "abstract-float"; } |
Ben Clayton | 23696b1 | 2022-05-18 21:56:28 +0000 | [diff] [blame] | 415 | }; |
| 416 | |
| 417 | /// Helper for building abstract integer types and expressions |
| 418 | template <> |
| 419 | struct DataType<AInt> { |
Ben Clayton | a8d5228 | 2022-05-25 21:07:04 +0000 | [diff] [blame] | 420 | /// The element type |
| 421 | using ElementType = AInt; |
| 422 | |
Ben Clayton | 23696b1 | 2022-05-18 21:56:28 +0000 | [diff] [blame] | 423 | /// false as AFloat is not a composite type |
| 424 | static constexpr bool is_composite = false; |
| 425 | |
Ben Clayton | a2ce4ec | 2022-05-20 12:11:00 +0000 | [diff] [blame] | 426 | /// @returns nullptr, as abstract integers are un-typeable |
Ben Clayton | 971318f | 2023-02-14 13:52:43 +0000 | [diff] [blame] | 427 | static inline ast::Type AST(ProgramBuilder&) { return {}; } |
Ben Clayton | 23696b1 | 2022-05-18 21:56:28 +0000 | [diff] [blame] | 428 | /// @param b the ProgramBuilder |
| 429 | /// @return the semantic abstract-int type |
dan sinclair | 094ace6 | 2022-12-08 15:33:01 +0000 | [diff] [blame] | 430 | static inline const type::Type* Sem(ProgramBuilder& b) { return b.create<type::AbstractInt>(); } |
Ben Clayton | 23696b1 | 2022-05-18 21:56:28 +0000 | [diff] [blame] | 431 | /// @param b the ProgramBuilder |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 432 | /// @param args args of size 1 with the abstract-int value to init with |
Ben Clayton | 23696b1 | 2022-05-18 21:56:28 +0000 | [diff] [blame] | 433 | /// @return a new AST abstract-int literal value expression |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 434 | static inline const ast::Expression* Expr(ProgramBuilder& b, utils::VectorRef<Scalar> args) { |
| 435 | return b.Expr(std::get<AInt>(args[0])); |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 436 | } |
| 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 Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 441 | return Expr(b, utils::Vector<Scalar, 1>{static_cast<ElementType>(v)}); |
Ben Clayton | 23696b1 | 2022-05-18 21:56:28 +0000 | [diff] [blame] | 442 | } |
Ben Clayton | a2ce4ec | 2022-05-20 12:11:00 +0000 | [diff] [blame] | 443 | /// @returns the WGSL name for the type |
| 444 | static inline std::string Name() { return "abstract-int"; } |
Ben Clayton | 23696b1 | 2022-05-18 21:56:28 +0000 | [diff] [blame] | 445 | }; |
| 446 | |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 447 | /// Helper for building vector types and expressions |
Ben Clayton | 4391975 | 2022-03-07 17:05:28 +0000 | [diff] [blame] | 448 | template <uint32_t N, typename T> |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 449 | struct DataType<vec<N, T>> { |
Ben Clayton | a8d5228 | 2022-05-25 21:07:04 +0000 | [diff] [blame] | 450 | /// The element type |
| 451 | using ElementType = T; |
| 452 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 453 | /// true as vectors are a composite type |
| 454 | static constexpr bool is_composite = true; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 455 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 456 | /// @param b the ProgramBuilder |
| 457 | /// @return a new AST vector type |
Ben Clayton | 971318f | 2023-02-14 13:52:43 +0000 | [diff] [blame] | 458 | 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 Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 464 | } |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 465 | /// @param b the ProgramBuilder |
| 466 | /// @return the semantic vector type |
dan sinclair | 5f764d8 | 2022-12-08 00:32:27 +0000 | [diff] [blame] | 467 | static inline const type::Type* Sem(ProgramBuilder& b) { |
dan sinclair | 0e780da | 2022-12-08 22:21:24 +0000 | [diff] [blame] | 468 | return b.create<type::Vector>(DataType<T>::Sem(b), N); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 469 | } |
| 470 | /// @param b the ProgramBuilder |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 471 | /// @param args args of size 1 or N with values of type T to initialize with |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 472 | /// @return a new AST vector value expression |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 473 | static inline const ast::Expression* Expr(ProgramBuilder& b, utils::VectorRef<Scalar> args) { |
Ben Clayton | 01ac21c | 2023-02-07 16:14:25 +0000 | [diff] [blame] | 474 | return b.Call(AST(b), ExprArgs(b, std::move(args))); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 475 | } |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 476 | /// @param b the ProgramBuilder |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 477 | /// @param args args of size 1 or N with values of type T to initialize with |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 478 | /// @return the list of expressions that are used to construct the vector |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 479 | static inline auto ExprArgs(ProgramBuilder& b, utils::VectorRef<Scalar> args) { |
| 480 | const bool one_value = args.Length() == 1; |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 481 | utils::Vector<const ast::Expression*, N> r; |
| 482 | for (size_t i = 0; i < N; ++i) { |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 483 | r.Push(DataType<T>::Expr(b, utils::Vector<Scalar, 1>{one_value ? args[0] : args[i]})); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 484 | } |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 485 | 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 Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 491 | return Expr(b, utils::Vector<Scalar, 1>{static_cast<ElementType>(v)}); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 492 | } |
Ben Clayton | a2ce4ec | 2022-05-20 12:11:00 +0000 | [diff] [blame] | 493 | /// @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 Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 497 | }; |
| 498 | |
| 499 | /// Helper for building matrix types and expressions |
Ben Clayton | 4391975 | 2022-03-07 17:05:28 +0000 | [diff] [blame] | 500 | template <uint32_t N, uint32_t M, typename T> |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 501 | struct DataType<mat<N, M, T>> { |
Ben Clayton | a8d5228 | 2022-05-25 21:07:04 +0000 | [diff] [blame] | 502 | /// The element type |
| 503 | using ElementType = T; |
| 504 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 505 | /// true as matrices are a composite type |
| 506 | static constexpr bool is_composite = true; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 507 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 508 | /// @param b the ProgramBuilder |
| 509 | /// @return a new AST matrix type |
Ben Clayton | 971318f | 2023-02-14 13:52:43 +0000 | [diff] [blame] | 510 | 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 Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 516 | } |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 517 | /// @param b the ProgramBuilder |
| 518 | /// @return the semantic matrix type |
dan sinclair | 5f764d8 | 2022-12-08 00:32:27 +0000 | [diff] [blame] | 519 | static inline const type::Type* Sem(ProgramBuilder& b) { |
dan sinclair | 0e780da | 2022-12-08 22:21:24 +0000 | [diff] [blame] | 520 | auto* column_type = b.create<type::Vector>(DataType<T>::Sem(b), M); |
| 521 | return b.create<type::Matrix>(column_type, N); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 522 | } |
| 523 | /// @param b the ProgramBuilder |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 524 | /// @param args args of size 1 or N*M with values of type T to initialize with |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 525 | /// @return a new AST matrix value expression |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 526 | static inline const ast::Expression* Expr(ProgramBuilder& b, utils::VectorRef<Scalar> args) { |
Ben Clayton | 01ac21c | 2023-02-07 16:14:25 +0000 | [diff] [blame] | 527 | return b.Call(AST(b), ExprArgs(b, std::move(args))); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 528 | } |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 529 | /// @param b the ProgramBuilder |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 530 | /// @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 Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 532 | static inline auto ExprArgs(ProgramBuilder& b, utils::VectorRef<Scalar> args) { |
| 533 | const bool one_value = args.Length() == 1; |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 534 | 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 Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 538 | r.Push(DataType<vec<M, T>>::Expr(b, utils::Vector<Scalar, 1>{args[0]})); |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 539 | } else { |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 540 | utils::Vector<Scalar, M> v; |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 541 | for (size_t j = 0; j < M; ++j) { |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 542 | v.Push(args[next++]); |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 543 | } |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 544 | r.Push(DataType<vec<M, T>>::Expr(b, std::move(v))); |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 545 | } |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 546 | } |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 547 | 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 Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 553 | return Expr(b, utils::Vector<Scalar, 1>{static_cast<ElementType>(v)}); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 554 | } |
Ben Clayton | a2ce4ec | 2022-05-20 12:11:00 +0000 | [diff] [blame] | 555 | /// @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 Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 560 | }; |
| 561 | |
| 562 | /// Helper for building alias types and expressions |
| 563 | template <typename T, int ID> |
| 564 | struct DataType<alias<T, ID>> { |
Ben Clayton | a8d5228 | 2022-05-25 21:07:04 +0000 | [diff] [blame] | 565 | /// The element type |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 566 | using ElementType = typename DataType<T>::ElementType; |
Ben Clayton | a8d5228 | 2022-05-25 21:07:04 +0000 | [diff] [blame] | 567 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 568 | /// true if the aliased type is a composite type |
| 569 | static constexpr bool is_composite = DataType<T>::is_composite; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 570 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 571 | /// @param b the ProgramBuilder |
| 572 | /// @return a new AST alias type |
Ben Clayton | 971318f | 2023-02-14 13:52:43 +0000 | [diff] [blame] | 573 | static inline ast::Type AST(ProgramBuilder& b) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 574 | auto name = b.Symbols().Register("alias_" + std::to_string(ID)); |
| 575 | if (!b.AST().LookupType(name)) { |
Ben Clayton | 971318f | 2023-02-14 13:52:43 +0000 | [diff] [blame] | 576 | auto type = DataType<T>::AST(b); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 577 | b.AST().AddTypeDecl(b.ty.alias(name, type)); |
| 578 | } |
Ben Clayton | 2117f80 | 2023-02-03 14:01:43 +0000 | [diff] [blame] | 579 | return b.ty(name); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 580 | } |
Ben Clayton | 971318f | 2023-02-14 13:52:43 +0000 | [diff] [blame] | 581 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 582 | /// @param b the ProgramBuilder |
| 583 | /// @return the semantic aliased type |
dan sinclair | 5f764d8 | 2022-12-08 00:32:27 +0000 | [diff] [blame] | 584 | static inline const type::Type* Sem(ProgramBuilder& b) { return DataType<T>::Sem(b); } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 585 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 586 | /// @param b the ProgramBuilder |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 587 | /// @param args the value nested elements will be initialized with |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 588 | /// @return a new AST expression of the alias type |
| 589 | template <bool IS_COMPOSITE = is_composite> |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 590 | static inline traits::EnableIf<!IS_COMPOSITE, const ast::Expression*> Expr( |
| 591 | ProgramBuilder& b, |
| 592 | utils::VectorRef<Scalar> args) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 593 | // Cast |
Ben Clayton | 01ac21c | 2023-02-07 16:14:25 +0000 | [diff] [blame] | 594 | return b.Call(AST(b), DataType<T>::Expr(b, std::move(args))); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 595 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 596 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 597 | /// @param b the ProgramBuilder |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 598 | /// @param args the value nested elements will be initialized with |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 599 | /// @return a new AST expression of the alias type |
| 600 | template <bool IS_COMPOSITE = is_composite> |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 601 | static inline traits::EnableIf<IS_COMPOSITE, const ast::Expression*> Expr( |
| 602 | ProgramBuilder& b, |
| 603 | utils::VectorRef<Scalar> args) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 604 | // Construct |
Ben Clayton | 01ac21c | 2023-02-07 16:14:25 +0000 | [diff] [blame] | 605 | return b.Call(AST(b), DataType<T>::ExprArgs(b, std::move(args))); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 606 | } |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 607 | |
| 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 Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 612 | return Expr(b, utils::Vector<Scalar, 1>{static_cast<ElementType>(v)}); |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 613 | } |
| 614 | |
Ben Clayton | a2ce4ec | 2022-05-20 12:11:00 +0000 | [diff] [blame] | 615 | /// @returns the WGSL name for the type |
| 616 | static inline std::string Name() { return "alias_" + std::to_string(ID); } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 617 | }; |
| 618 | |
| 619 | /// Helper for building pointer types and expressions |
| 620 | template <typename T> |
| 621 | struct DataType<ptr<T>> { |
Ben Clayton | a8d5228 | 2022-05-25 21:07:04 +0000 | [diff] [blame] | 622 | /// The element type |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 623 | using ElementType = typename DataType<T>::ElementType; |
Ben Clayton | a8d5228 | 2022-05-25 21:07:04 +0000 | [diff] [blame] | 624 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 625 | /// true if the pointer type is a composite type |
| 626 | static constexpr bool is_composite = false; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 627 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 628 | /// @param b the ProgramBuilder |
| 629 | /// @return a new AST alias type |
Ben Clayton | 971318f | 2023-02-14 13:52:43 +0000 | [diff] [blame] | 630 | static inline ast::Type AST(ProgramBuilder& b) { |
dan sinclair | 2a65163 | 2023-02-19 04:03:55 +0000 | [diff] [blame] | 631 | return b.ty.pointer(DataType<T>::AST(b), builtin::AddressSpace::kPrivate, |
dan sinclair | b6cc4cb | 2023-02-19 04:01:29 +0000 | [diff] [blame] | 632 | builtin::Access::kUndefined); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 633 | } |
| 634 | /// @param b the ProgramBuilder |
| 635 | /// @return the semantic aliased type |
dan sinclair | 5f764d8 | 2022-12-08 00:32:27 +0000 | [diff] [blame] | 636 | static inline const type::Type* Sem(ProgramBuilder& b) { |
dan sinclair | 2a65163 | 2023-02-19 04:03:55 +0000 | [diff] [blame] | 637 | return b.create<type::Pointer>(DataType<T>::Sem(b), builtin::AddressSpace::kPrivate, |
dan sinclair | b6cc4cb | 2023-02-19 04:01:29 +0000 | [diff] [blame] | 638 | builtin::Access::kReadWrite); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 639 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 640 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 641 | /// @param b the ProgramBuilder |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 642 | /// @return a new AST expression of the pointer type |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 643 | static inline const ast::Expression* Expr(ProgramBuilder& b, |
| 644 | utils::VectorRef<Scalar> /*unused*/) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 645 | auto sym = b.Symbols().New("global_for_ptr"); |
dan sinclair | 2a65163 | 2023-02-19 04:03:55 +0000 | [diff] [blame] | 646 | b.GlobalVar(sym, DataType<T>::AST(b), builtin::AddressSpace::kPrivate); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 647 | return b.AddressOf(sym); |
| 648 | } |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 649 | |
| 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 Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 654 | return Expr(b, utils::Vector<Scalar, 1>{static_cast<ElementType>(v)}); |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 655 | } |
| 656 | |
Ben Clayton | a2ce4ec | 2022-05-20 12:11:00 +0000 | [diff] [blame] | 657 | /// @returns the WGSL name for the type |
| 658 | static inline std::string Name() { return "ptr<" + DataType<T>::Name() + ">"; } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 659 | }; |
| 660 | |
| 661 | /// Helper for building array types and expressions |
Ben Clayton | 4391975 | 2022-03-07 17:05:28 +0000 | [diff] [blame] | 662 | template <uint32_t N, typename T> |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 663 | struct DataType<array<N, T>> { |
Ben Clayton | a8d5228 | 2022-05-25 21:07:04 +0000 | [diff] [blame] | 664 | /// The element type |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 665 | using ElementType = typename DataType<T>::ElementType; |
Ben Clayton | a8d5228 | 2022-05-25 21:07:04 +0000 | [diff] [blame] | 666 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 667 | /// true as arrays are a composite type |
| 668 | static constexpr bool is_composite = true; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 669 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 670 | /// @param b the ProgramBuilder |
| 671 | /// @return a new AST array type |
Ben Clayton | 971318f | 2023-02-14 13:52:43 +0000 | [diff] [blame] | 672 | static inline ast::Type AST(ProgramBuilder& b) { |
| 673 | if (auto ast = DataType<T>::AST(b)) { |
Ben Clayton | 4a65620 | 2022-08-01 17:36:54 +0000 | [diff] [blame] | 674 | return b.ty.array(ast, u32(N)); |
| 675 | } |
Ben Clayton | 971318f | 2023-02-14 13:52:43 +0000 | [diff] [blame] | 676 | return b.ty.array<Infer>(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 677 | } |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 678 | /// @param b the ProgramBuilder |
| 679 | /// @return the semantic array type |
dan sinclair | 5f764d8 | 2022-12-08 00:32:27 +0000 | [diff] [blame] | 680 | static inline const type::Type* Sem(ProgramBuilder& b) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 681 | auto* el = DataType<T>::Sem(b); |
dan sinclair | 5f764d8 | 2022-12-08 00:32:27 +0000 | [diff] [blame] | 682 | const type::ArrayCount* count = nullptr; |
dan sinclair | 78f8067 | 2022-09-22 22:28:21 +0000 | [diff] [blame] | 683 | if (N == 0) { |
dan sinclair | 5f764d8 | 2022-12-08 00:32:27 +0000 | [diff] [blame] | 684 | count = b.create<type::RuntimeArrayCount>(); |
dan sinclair | 4b1d79e | 2022-12-01 23:45:18 +0000 | [diff] [blame] | 685 | } else { |
dan sinclair | 5f764d8 | 2022-12-08 00:32:27 +0000 | [diff] [blame] | 686 | count = b.create<type::ConstantArrayCount>(N); |
dan sinclair | 78f8067 | 2022-09-22 22:28:21 +0000 | [diff] [blame] | 687 | } |
dan sinclair | 946858a | 2022-12-08 22:21:24 +0000 | [diff] [blame] | 688 | return b.create<type::Array>( |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 689 | /* element */ el, |
dan sinclair | 78f8067 | 2022-09-22 22:28:21 +0000 | [diff] [blame] | 690 | /* count */ count, |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 691 | /* align */ el->Align(), |
Ben Clayton | 4a65620 | 2022-08-01 17:36:54 +0000 | [diff] [blame] | 692 | /* size */ N * el->Size(), |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 693 | /* stride */ el->Align(), |
| 694 | /* implicit_stride */ el->Align()); |
| 695 | } |
| 696 | /// @param b the ProgramBuilder |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 697 | /// @param args args of size 1 or N with values of type T to initialize with |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 698 | /// with |
| 699 | /// @return a new AST array value expression |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 700 | static inline const ast::Expression* Expr(ProgramBuilder& b, utils::VectorRef<Scalar> args) { |
Ben Clayton | 01ac21c | 2023-02-07 16:14:25 +0000 | [diff] [blame] | 701 | return b.Call(AST(b), ExprArgs(b, std::move(args))); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 702 | } |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 703 | /// @param b the ProgramBuilder |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 704 | /// @param args args of size 1 or N with values of type T to initialize with |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 705 | /// @return the list of expressions that are used to construct the array |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 706 | static inline auto ExprArgs(ProgramBuilder& b, utils::VectorRef<Scalar> args) { |
| 707 | const bool one_value = args.Length() == 1; |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 708 | utils::Vector<const ast::Expression*, N> r; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 709 | for (uint32_t i = 0; i < N; i++) { |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 710 | r.Push(DataType<T>::Expr(b, utils::Vector<Scalar, 1>{one_value ? args[0] : args[i]})); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 711 | } |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 712 | 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 Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 718 | return Expr(b, utils::Vector<Scalar, 1>{static_cast<ElementType>(v)}); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 719 | } |
Ben Clayton | a2ce4ec | 2022-05-20 12:11:00 +0000 | [diff] [blame] | 720 | /// @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 Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 724 | }; |
| 725 | |
| 726 | /// Struct of all creation pointer types |
| 727 | struct CreatePtrs { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 728 | /// ast node type create function |
| 729 | ast_type_func_ptr ast; |
| 730 | /// ast expression type create function |
| 731 | ast_expr_func_ptr expr; |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 732 | /// ast expression type create function from double arg |
| 733 | ast_expr_from_double_func_ptr expr_from_double; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 734 | /// sem type create function |
| 735 | sem_type_func_ptr sem; |
Ben Clayton | 75bc93c | 2022-10-11 20:36:48 +0000 | [diff] [blame] | 736 | /// type name function |
| 737 | type_name_func_ptr name; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 738 | }; |
| 739 | |
Ben Clayton | 75bc93c | 2022-10-11 20:36:48 +0000 | [diff] [blame] | 740 | /// @param o the std::ostream to write to |
| 741 | /// @param ptrs the CreatePtrs |
| 742 | /// @return the std::ostream so calls can be chained |
| 743 | inline std::ostream& operator<<(std::ostream& o, const CreatePtrs& ptrs) { |
| 744 | return o << (ptrs.name ? ptrs.name() : "<unknown>"); |
| 745 | } |
| 746 | |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 747 | /// Returns a CreatePtrs struct instance with all creation pointer types for |
| 748 | /// type `T` |
| 749 | template <typename T> |
| 750 | constexpr CreatePtrs CreatePtrsFor() { |
Ben Clayton | 75bc93c | 2022-10-11 20:36:48 +0000 | [diff] [blame] | 751 | return {DataType<T>::AST, DataType<T>::Expr, DataType<T>::ExprFromDouble, DataType<T>::Sem, |
| 752 | DataType<T>::Name}; |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 753 | } |
| 754 | |
Antonio Maiorano | d490867 | 2022-11-25 05:47:42 +0000 | [diff] [blame] | 755 | /// True if DataType<T> is specialized for T, false otherwise. |
| 756 | template <typename T> |
| 757 | const bool IsDataTypeSpecializedFor = |
| 758 | !std::is_same_v<typename DataType<T>::ElementType, UnspecializedElementType>; |
| 759 | |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 760 | /// Value is used to create Values with a Scalar vector initializer. |
| 761 | struct Value { |
| 762 | /// Creates a Value for type T initialized with `args` |
Antonio Maiorano | d490867 | 2022-11-25 05:47:42 +0000 | [diff] [blame] | 763 | /// @param args the scalar args |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 764 | /// @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 Maiorano | 0566185 | 2022-12-20 18:34:06 +0000 | [diff] [blame] | 770 | std::move(args), // |
| 771 | CreatePtrsFor<T>(), // |
| 772 | tint::IsAbstract<EL_TY>, // |
| 773 | tint::IsIntegral<EL_TY>, // |
| 774 | tint::FriendlyName<EL_TY>(), |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 775 | }; |
Antonio Maiorano | 29fb8f8 | 2022-10-17 16:11:02 +0000 | [diff] [blame] | 776 | } |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 777 | |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 778 | /// Creates an `ast::Expression` for the type T passing in previously stored args |
| 779 | /// @param b the ProgramBuilder |
| 780 | /// @returns an expression node |
Antonio Maiorano | 0566185 | 2022-12-20 18:34:06 +0000 | [diff] [blame] | 781 | const ast::Expression* Expr(ProgramBuilder& b) const { return (*create_ptrs.expr)(b, args); } |
Antonio Maiorano | 29fb8f8 | 2022-10-17 16:11:02 +0000 | [diff] [blame] | 782 | |
| 783 | /// Prints this value to the output stream |
| 784 | /// @param o the output stream |
| 785 | /// @returns input argument `o` |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 786 | 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 Maiorano | 29fb8f8 | 2022-10-17 16:11:02 +0000 | [diff] [blame] | 791 | o << ", "; |
| 792 | } |
| 793 | } |
| 794 | o << ")"; |
| 795 | return o; |
| 796 | } |
| 797 | |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 798 | /// The arguments used to construct the value |
| 799 | utils::Vector<Scalar, 4> args; |
Antonio Maiorano | 0566185 | 2022-12-20 18:34:06 +0000 | [diff] [blame] | 800 | /// CreatePtrs for value's type used to create an expression with `args` |
| 801 | builder::CreatePtrs create_ptrs; |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 802 | /// 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 Maiorano | d490867 | 2022-11-25 05:47:42 +0000 | [diff] [blame] | 808 | }; |
| 809 | |
| 810 | /// Prints Value to ostream |
| 811 | inline std::ostream& operator<<(std::ostream& o, const Value& value) { |
| 812 | return value.Print(o); |
Antonio Maiorano | 29aa613 | 2022-09-07 19:34:44 +0000 | [diff] [blame] | 813 | } |
| 814 | |
Antonio Maiorano | d490867 | 2022-11-25 05:47:42 +0000 | [diff] [blame] | 815 | /// True if T is Value, false otherwise |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 816 | template <typename T> |
Antonio Maiorano | d490867 | 2022-11-25 05:47:42 +0000 | [diff] [blame] | 817 | constexpr bool IsValue = std::is_same_v<T, Value>; |
| 818 | |
| 819 | /// Creates a Value of DataType<T> from a scalar `v` |
| 820 | template <typename T> |
| 821 | Value Val(T v) { |
Antonio Maiorano | 171c542 | 2022-11-30 16:02:45 +0000 | [diff] [blame] | 822 | static_assert(traits::IsTypeIn<T, Scalar>, "v must be a Number of bool"); |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 823 | return Value::Create<T>(utils::Vector<Scalar, 1>{v}); |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 824 | } |
| 825 | |
Antonio Maiorano | d490867 | 2022-11-25 05:47:42 +0000 | [diff] [blame] | 826 | /// Creates a Value of DataType<vec<N, T>> from N scalar `args` |
Antonio Maiorano | 0566185 | 2022-12-20 18:34:06 +0000 | [diff] [blame] | 827 | template <typename... Ts> |
| 828 | Value Vec(Ts... args) { |
| 829 | using FirstT = std::tuple_element_t<0, std::tuple<Ts...>>; |
Antonio Maiorano | c73d673 | 2022-12-23 21:09:10 +0000 | [diff] [blame] | 830 | static_assert(sizeof...(args) >= 2 && sizeof...(args) <= 4, "Invalid vector size"); |
Antonio Maiorano | 0566185 | 2022-12-20 18:34:06 +0000 | [diff] [blame] | 831 | static_assert(std::conjunction_v<std::is_same<FirstT, Ts>...>, |
| 832 | "Vector args must all be the same type"); |
Antonio Maiorano | d490867 | 2022-11-25 05:47:42 +0000 | [diff] [blame] | 833 | constexpr size_t N = sizeof...(args); |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 834 | utils::Vector<Scalar, sizeof...(args)> v{args...}; |
| 835 | return Value::Create<vec<N, FirstT>>(std::move(v)); |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 836 | } |
| 837 | |
Antonio Maiorano | 6b4622f | 2022-12-22 16:27:43 +0000 | [diff] [blame] | 838 | /// Creates a Value of DataType<array<N, T>> from N scalar `args` |
| 839 | template <typename... Ts> |
| 840 | Value 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 Maiorano | d490867 | 2022-11-25 05:47:42 +0000 | [diff] [blame] | 849 | /// Creates a Value of DataType<mat<C,R,T> from C*R scalar `args` |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 850 | template <size_t C, size_t R, typename T> |
Antonio Maiorano | d490867 | 2022-11-25 05:47:42 +0000 | [diff] [blame] | 851 | Value Mat(const T (&m_in)[C][R]) { |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 852 | utils::Vector<Scalar, C * R> m; |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 853 | 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 Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 858 | return Value::Create<mat<C, R, T>>(std::move(m)); |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 859 | } |
| 860 | |
Antonio Maiorano | d490867 | 2022-11-25 05:47:42 +0000 | [diff] [blame] | 861 | /// Creates a Value of DataType<mat<2,R,T> from column vectors `c0` and `c1` |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 862 | template <typename T, size_t R> |
Antonio Maiorano | d490867 | 2022-11-25 05:47:42 +0000 | [diff] [blame] | 863 | Value Mat(const T (&c0)[R], const T (&c1)[R]) { |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 864 | constexpr size_t C = 2; |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 865 | utils::Vector<Scalar, C * R> m; |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 866 | for (auto v : c0) { |
| 867 | m.Push(v); |
| 868 | } |
| 869 | for (auto v : c1) { |
| 870 | m.Push(v); |
| 871 | } |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 872 | return Value::Create<mat<C, R, T>>(std::move(m)); |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 873 | } |
| 874 | |
Antonio Maiorano | d490867 | 2022-11-25 05:47:42 +0000 | [diff] [blame] | 875 | /// Creates a Value of DataType<mat<3,R,T> from column vectors `c0`, `c1`, and `c2` |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 876 | template <typename T, size_t R> |
Antonio Maiorano | d490867 | 2022-11-25 05:47:42 +0000 | [diff] [blame] | 877 | Value Mat(const T (&c0)[R], const T (&c1)[R], const T (&c2)[R]) { |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 878 | constexpr size_t C = 3; |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 879 | utils::Vector<Scalar, C * R> m; |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 880 | 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 Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 889 | return Value::Create<mat<C, R, T>>(std::move(m)); |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 890 | } |
| 891 | |
Antonio Maiorano | d490867 | 2022-11-25 05:47:42 +0000 | [diff] [blame] | 892 | /// Creates a Value of DataType<mat<4,R,T> from column vectors `c0`, `c1`, `c2`, and `c3` |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 893 | template <typename T, size_t R> |
Antonio Maiorano | d490867 | 2022-11-25 05:47:42 +0000 | [diff] [blame] | 894 | Value Mat(const T (&c0)[R], const T (&c1)[R], const T (&c2)[R], const T (&c3)[R]) { |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 895 | constexpr size_t C = 4; |
Ben Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 896 | utils::Vector<Scalar, C * R> m; |
Antonio Maiorano | b6d52438 | 2022-08-31 22:59:08 +0000 | [diff] [blame] | 897 | 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 Clayton | 95d174a | 2022-11-25 15:30:51 +0000 | [diff] [blame] | 909 | return Value::Create<mat<C, R, T>>(std::move(m)); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 910 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 911 | } // namespace builder |
dan sinclair | d209379 | 2022-04-07 17:45:45 +0000 | [diff] [blame] | 912 | } // namespace tint::resolver |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 913 | |
| 914 | #endif // SRC_TINT_RESOLVER_RESOLVER_TEST_HELPER_H_ |