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_PROGRAM_BUILDER_H_ 16 #define SRC_PROGRAM_BUILDER_H_ 17 18 #include <string> 19 #include <unordered_set> 20 #include <utility> 21 22 #include "src/ast/alias.h" 23 #include "src/ast/array.h" 24 #include "src/ast/assignment_statement.h" 25 #include "src/ast/atomic.h" 26 #include "src/ast/binary_expression.h" 27 #include "src/ast/binding_decoration.h" 28 #include "src/ast/bitcast_expression.h" 29 #include "src/ast/bool.h" 30 #include "src/ast/bool_literal_expression.h" 31 #include "src/ast/break_statement.h" 32 #include "src/ast/call_expression.h" 33 #include "src/ast/call_statement.h" 34 #include "src/ast/case_statement.h" 35 #include "src/ast/continue_statement.h" 36 #include "src/ast/depth_multisampled_texture.h" 37 #include "src/ast/depth_texture.h" 38 #include "src/ast/disable_validation_decoration.h" 39 #include "src/ast/discard_statement.h" 40 #include "src/ast/external_texture.h" 41 #include "src/ast/f32.h" 42 #include "src/ast/fallthrough_statement.h" 43 #include "src/ast/float_literal_expression.h" 44 #include "src/ast/for_loop_statement.h" 45 #include "src/ast/i32.h" 46 #include "src/ast/if_statement.h" 47 #include "src/ast/index_accessor_expression.h" 48 #include "src/ast/interpolate_decoration.h" 49 #include "src/ast/invariant_decoration.h" 50 #include "src/ast/loop_statement.h" 51 #include "src/ast/matrix.h" 52 #include "src/ast/member_accessor_expression.h" 53 #include "src/ast/module.h" 54 #include "src/ast/multisampled_texture.h" 55 #include "src/ast/override_decoration.h" 56 #include "src/ast/phony_expression.h" 57 #include "src/ast/pointer.h" 58 #include "src/ast/return_statement.h" 59 #include "src/ast/sampled_texture.h" 60 #include "src/ast/sampler.h" 61 #include "src/ast/sint_literal_expression.h" 62 #include "src/ast/stage_decoration.h" 63 #include "src/ast/storage_texture.h" 64 #include "src/ast/stride_decoration.h" 65 #include "src/ast/struct_block_decoration.h" 66 #include "src/ast/struct_member_align_decoration.h" 67 #include "src/ast/struct_member_offset_decoration.h" 68 #include "src/ast/struct_member_size_decoration.h" 69 #include "src/ast/switch_statement.h" 70 #include "src/ast/type_name.h" 71 #include "src/ast/u32.h" 72 #include "src/ast/uint_literal_expression.h" 73 #include "src/ast/unary_op_expression.h" 74 #include "src/ast/variable_decl_statement.h" 75 #include "src/ast/vector.h" 76 #include "src/ast/void.h" 77 #include "src/ast/workgroup_decoration.h" 78 #include "src/program.h" 79 #include "src/program_id.h" 80 #include "src/sem/array.h" 81 #include "src/sem/bool_type.h" 82 #include "src/sem/depth_texture_type.h" 83 #include "src/sem/external_texture_type.h" 84 #include "src/sem/f32_type.h" 85 #include "src/sem/i32_type.h" 86 #include "src/sem/matrix_type.h" 87 #include "src/sem/multisampled_texture_type.h" 88 #include "src/sem/pointer_type.h" 89 #include "src/sem/sampled_texture_type.h" 90 #include "src/sem/storage_texture_type.h" 91 #include "src/sem/struct.h" 92 #include "src/sem/u32_type.h" 93 #include "src/sem/vector_type.h" 94 #include "src/sem/void_type.h" 95 96 #ifdef INCLUDE_TINT_TINT_H_ 97 #error "internal tint header being #included from tint.h" 98 #endif 99 100 // Forward declarations 101 namespace tint { 102 namespace ast { 103 class VariableDeclStatement; 104 } // namespace ast 105 } // namespace tint 106 107 namespace tint { 108 class CloneContext; 109 110 /// ProgramBuilder is a mutable builder for a Program. 111 /// To construct a Program, populate the builder and then `std::move` it to a 112 /// Program. 113 class ProgramBuilder { 114 /// A helper used to disable overloads if the first type in `TYPES` is a 115 /// Source. Used to avoid ambiguities in overloads that take a Source as the 116 /// first parameter and those that perfectly-forward the first argument. 117 template <typename... TYPES> 118 using DisableIfSource = traits::EnableIfIsNotType< 119 traits::Decay<traits::NthTypeOf<0, TYPES..., void>>, 120 Source>; 121 122 /// VarOptionals is a helper for accepting a number of optional, extra 123 /// arguments for Var() and Global(). 124 struct VarOptionals { 125 template <typename... ARGS> VarOptionalsVarOptionals126 explicit VarOptionals(ARGS&&... args) { 127 Apply(std::forward<ARGS>(args)...); 128 } 129 ~VarOptionals(); 130 131 ast::StorageClass storage = ast::StorageClass::kNone; 132 ast::Access access = ast::Access::kUndefined; 133 const ast::Expression* constructor = nullptr; 134 ast::DecorationList decorations = {}; 135 136 private: SetVarOptionals137 void Set(ast::StorageClass sc) { storage = sc; } SetVarOptionals138 void Set(ast::Access ac) { access = ac; } SetVarOptionals139 void Set(const ast::Expression* c) { constructor = c; } SetVarOptionals140 void Set(const ast::DecorationList& l) { decorations = l; } 141 142 template <typename FIRST, typename... ARGS> ApplyVarOptionals143 void Apply(FIRST&& first, ARGS&&... args) { 144 Set(std::forward<FIRST>(first)); 145 Apply(std::forward<ARGS>(args)...); 146 } ApplyVarOptionals147 void Apply() {} 148 }; 149 150 public: 151 /// ASTNodeAllocator is an alias to BlockAllocator<ast::Node> 152 using ASTNodeAllocator = BlockAllocator<ast::Node>; 153 154 /// SemNodeAllocator is an alias to BlockAllocator<sem::Node> 155 using SemNodeAllocator = BlockAllocator<sem::Node>; 156 157 /// `i32` is a type alias to `int`. 158 /// Useful for passing to template methods such as `vec2<i32>()` to imitate 159 /// WGSL syntax. 160 /// Note: this is intentionally not aliased to uint32_t as we want integer 161 /// literals passed to the builder to match WGSL's integer literal types. 162 using i32 = decltype(1); 163 /// `u32` is a type alias to `unsigned int`. 164 /// Useful for passing to template methods such as `vec2<u32>()` to imitate 165 /// WGSL syntax. 166 /// Note: this is intentionally not aliased to uint32_t as we want integer 167 /// literals passed to the builder to match WGSL's integer literal types. 168 using u32 = decltype(1u); 169 /// `f32` is a type alias to `float` 170 /// Useful for passing to template methods such as `vec2<f32>()` to imitate 171 /// WGSL syntax. 172 using f32 = float; 173 174 /// Constructor 175 ProgramBuilder(); 176 177 /// Move constructor 178 /// @param rhs the builder to move 179 ProgramBuilder(ProgramBuilder&& rhs); 180 181 /// Destructor 182 virtual ~ProgramBuilder(); 183 184 /// Move assignment operator 185 /// @param rhs the builder to move 186 /// @return this builder 187 ProgramBuilder& operator=(ProgramBuilder&& rhs); 188 189 /// Wrap returns a new ProgramBuilder wrapping the Program `program` without 190 /// making a deep clone of the Program contents. 191 /// ProgramBuilder returned by Wrap() is intended to temporarily extend an 192 /// existing immutable program. 193 /// As the returned ProgramBuilder wraps `program`, `program` must not be 194 /// destructed or assigned while using the returned ProgramBuilder. 195 /// TODO(bclayton) - Evaluate whether there are safer alternatives to this 196 /// function. See crbug.com/tint/460. 197 /// @param program the immutable Program to wrap 198 /// @return the ProgramBuilder that wraps `program` 199 static ProgramBuilder Wrap(const Program* program); 200 201 /// @returns the unique identifier for this program ID()202 ProgramID ID() const { return id_; } 203 204 /// @returns a reference to the program's types Types()205 sem::Manager& Types() { 206 AssertNotMoved(); 207 return types_; 208 } 209 210 /// @returns a reference to the program's types Types()211 const sem::Manager& Types() const { 212 AssertNotMoved(); 213 return types_; 214 } 215 216 /// @returns a reference to the program's AST nodes storage ASTNodes()217 ASTNodeAllocator& ASTNodes() { 218 AssertNotMoved(); 219 return ast_nodes_; 220 } 221 222 /// @returns a reference to the program's AST nodes storage ASTNodes()223 const ASTNodeAllocator& ASTNodes() const { 224 AssertNotMoved(); 225 return ast_nodes_; 226 } 227 228 /// @returns a reference to the program's semantic nodes storage SemNodes()229 SemNodeAllocator& SemNodes() { 230 AssertNotMoved(); 231 return sem_nodes_; 232 } 233 234 /// @returns a reference to the program's semantic nodes storage SemNodes()235 const SemNodeAllocator& SemNodes() const { 236 AssertNotMoved(); 237 return sem_nodes_; 238 } 239 240 /// @returns a reference to the program's AST root Module AST()241 ast::Module& AST() { 242 AssertNotMoved(); 243 return *ast_; 244 } 245 246 /// @returns a reference to the program's AST root Module AST()247 const ast::Module& AST() const { 248 AssertNotMoved(); 249 return *ast_; 250 } 251 252 /// @returns a reference to the program's semantic info Sem()253 sem::Info& Sem() { 254 AssertNotMoved(); 255 return sem_; 256 } 257 258 /// @returns a reference to the program's semantic info Sem()259 const sem::Info& Sem() const { 260 AssertNotMoved(); 261 return sem_; 262 } 263 264 /// @returns a reference to the program's SymbolTable Symbols()265 SymbolTable& Symbols() { 266 AssertNotMoved(); 267 return symbols_; 268 } 269 270 /// @returns a reference to the program's SymbolTable Symbols()271 const SymbolTable& Symbols() const { 272 AssertNotMoved(); 273 return symbols_; 274 } 275 276 /// @returns a reference to the program's diagnostics Diagnostics()277 diag::List& Diagnostics() { 278 AssertNotMoved(); 279 return diagnostics_; 280 } 281 282 /// @returns a reference to the program's diagnostics Diagnostics()283 const diag::List& Diagnostics() const { 284 AssertNotMoved(); 285 return diagnostics_; 286 } 287 288 /// Controls whether the Resolver will be run on the program when it is built. 289 /// @param enable the new flag value (defaults to true) SetResolveOnBuild(bool enable)290 void SetResolveOnBuild(bool enable) { resolve_on_build_ = enable; } 291 292 /// @return true if the Resolver will be run on the program when it is 293 /// built. ResolveOnBuild()294 bool ResolveOnBuild() const { return resolve_on_build_; } 295 296 /// @returns true if the program has no error diagnostics and is not missing 297 /// information 298 bool IsValid() const; 299 300 /// Creates a new ast::Node owned by the ProgramBuilder. When the 301 /// ProgramBuilder is destructed, the ast::Node will also be destructed. 302 /// @param source the Source of the node 303 /// @param args the arguments to pass to the type constructor 304 /// @returns the node pointer 305 template <typename T, typename... ARGS> create(const Source & source,ARGS &&...args)306 traits::EnableIfIsType<T, ast::Node>* create(const Source& source, 307 ARGS&&... args) { 308 AssertNotMoved(); 309 return ast_nodes_.Create<T>(id_, source, std::forward<ARGS>(args)...); 310 } 311 312 /// Creates a new ast::Node owned by the ProgramBuilder, injecting the current 313 /// Source as set by the last call to SetSource() as the only argument to the 314 /// constructor. 315 /// When the ProgramBuilder is destructed, the ast::Node will also be 316 /// destructed. 317 /// @returns the node pointer 318 template <typename T> create()319 traits::EnableIfIsType<T, ast::Node>* create() { 320 AssertNotMoved(); 321 return ast_nodes_.Create<T>(id_, source_); 322 } 323 324 /// Creates a new ast::Node owned by the ProgramBuilder, injecting the current 325 /// Source as set by the last call to SetSource() as the first argument to the 326 /// constructor. 327 /// When the ProgramBuilder is destructed, the ast::Node will also be 328 /// destructed. 329 /// @param arg0 the first arguments to pass to the type constructor 330 /// @param args the remaining arguments to pass to the type constructor 331 /// @returns the node pointer 332 template <typename T, typename ARG0, typename... ARGS> 333 traits::EnableIf</* T is ast::Node and ARG0 is not Source */ 334 traits::IsTypeOrDerived<T, ast::Node>::value && 335 !traits::IsTypeOrDerived<ARG0, Source>::value, 336 T>* create(ARG0 && arg0,ARGS &&...args)337 create(ARG0&& arg0, ARGS&&... args) { 338 AssertNotMoved(); 339 return ast_nodes_.Create<T>(id_, source_, std::forward<ARG0>(arg0), 340 std::forward<ARGS>(args)...); 341 } 342 343 /// Creates a new sem::Node owned by the ProgramBuilder. 344 /// When the ProgramBuilder is destructed, the sem::Node will also be 345 /// destructed. 346 /// @param args the arguments to pass to the type constructor 347 /// @returns the node pointer 348 template <typename T, typename... ARGS> 349 traits::EnableIf<traits::IsTypeOrDerived<T, sem::Node>::value && 350 !traits::IsTypeOrDerived<T, sem::Type>::value, 351 T>* create(ARGS &&...args)352 create(ARGS&&... args) { 353 AssertNotMoved(); 354 return sem_nodes_.Create<T>(std::forward<ARGS>(args)...); 355 } 356 357 /// Creates a new sem::Type owned by the ProgramBuilder. 358 /// When the ProgramBuilder is destructed, owned ProgramBuilder and the 359 /// returned`Type` will also be destructed. 360 /// Types are unique (de-aliased), and so calling create() for the same `T` 361 /// and arguments will return the same pointer. 362 /// @warning Use this method to acquire a type only if all of its type 363 /// information is provided in the constructor arguments `args`.<br> 364 /// If the type requires additional configuration after construction that 365 /// affect its fundamental type, build the type with `std::make_unique`, make 366 /// any necessary alterations and then call unique_type() instead. 367 /// @param args the arguments to pass to the type constructor 368 /// @returns the de-aliased type pointer 369 template <typename T, typename... ARGS> create(ARGS &&...args)370 traits::EnableIfIsType<T, sem::Type>* create(ARGS&&... args) { 371 static_assert(std::is_base_of<sem::Type, T>::value, 372 "T does not derive from sem::Type"); 373 AssertNotMoved(); 374 return types_.Get<T>(std::forward<ARGS>(args)...); 375 } 376 377 /// Marks this builder as moved, preventing any further use of the builder. 378 void MarkAsMoved(); 379 380 ////////////////////////////////////////////////////////////////////////////// 381 // TypesBuilder 382 ////////////////////////////////////////////////////////////////////////////// 383 384 /// TypesBuilder holds basic `tint` types and methods for constructing 385 /// complex types. 386 class TypesBuilder { 387 public: 388 /// Constructor 389 /// @param builder the program builder 390 explicit TypesBuilder(ProgramBuilder* builder); 391 392 /// @return the tint AST type for the C type `T`. 393 template <typename T> Of()394 const ast::Type* Of() const { 395 return CToAST<T>::get(this); 396 } 397 398 /// @returns a boolean type bool_()399 const ast::Bool* bool_() const { return builder->create<ast::Bool>(); } 400 401 /// @param source the Source of the node 402 /// @returns a boolean type bool_(const Source & source)403 const ast::Bool* bool_(const Source& source) const { 404 return builder->create<ast::Bool>(source); 405 } 406 407 /// @returns a f32 type f32()408 const ast::F32* f32() const { return builder->create<ast::F32>(); } 409 410 /// @param source the Source of the node 411 /// @returns a f32 type f32(const Source & source)412 const ast::F32* f32(const Source& source) const { 413 return builder->create<ast::F32>(source); 414 } 415 416 /// @returns a i32 type i32()417 const ast::I32* i32() const { return builder->create<ast::I32>(); } 418 419 /// @param source the Source of the node 420 /// @returns a i32 type i32(const Source & source)421 const ast::I32* i32(const Source& source) const { 422 return builder->create<ast::I32>(source); 423 } 424 425 /// @returns a u32 type u32()426 const ast::U32* u32() const { return builder->create<ast::U32>(); } 427 428 /// @param source the Source of the node 429 /// @returns a u32 type u32(const Source & source)430 const ast::U32* u32(const Source& source) const { 431 return builder->create<ast::U32>(source); 432 } 433 434 /// @returns a void type void_()435 const ast::Void* void_() const { return builder->create<ast::Void>(); } 436 437 /// @param source the Source of the node 438 /// @returns a void type void_(const Source & source)439 const ast::Void* void_(const Source& source) const { 440 return builder->create<ast::Void>(source); 441 } 442 443 /// @param type vector subtype 444 /// @param n vector width in elements 445 /// @return the tint AST type for a `n`-element vector of `type`. vec(const ast::Type * type,uint32_t n)446 const ast::Vector* vec(const ast::Type* type, uint32_t n) const { 447 return builder->create<ast::Vector>(type, n); 448 } 449 450 /// @param source the Source of the node 451 /// @param type vector subtype 452 /// @param n vector width in elements 453 /// @return the tint AST type for a `n`-element vector of `type`. vec(const Source & source,const ast::Type * type,uint32_t n)454 const ast::Vector* vec(const Source& source, 455 const ast::Type* type, 456 uint32_t n) const { 457 return builder->create<ast::Vector>(source, type, n); 458 } 459 460 /// @param type vector subtype 461 /// @return the tint AST type for a 2-element vector of `type`. vec2(const ast::Type * type)462 const ast::Vector* vec2(const ast::Type* type) const { 463 return vec(type, 2u); 464 } 465 466 /// @param type vector subtype 467 /// @return the tint AST type for a 3-element vector of `type`. vec3(const ast::Type * type)468 const ast::Vector* vec3(const ast::Type* type) const { 469 return vec(type, 3u); 470 } 471 472 /// @param type vector subtype 473 /// @return the tint AST type for a 4-element vector of `type`. vec4(const ast::Type * type)474 const ast::Vector* vec4(const ast::Type* type) const { 475 return vec(type, 4u); 476 } 477 478 /// @param n vector width in elements 479 /// @return the tint AST type for a `n`-element vector of `type`. 480 template <typename T> vec(uint32_t n)481 const ast::Vector* vec(uint32_t n) const { 482 return vec(Of<T>(), n); 483 } 484 485 /// @return the tint AST type for a 2-element vector of the C type `T`. 486 template <typename T> vec2()487 const ast::Vector* vec2() const { 488 return vec2(Of<T>()); 489 } 490 491 /// @return the tint AST type for a 3-element vector of the C type `T`. 492 template <typename T> vec3()493 const ast::Vector* vec3() const { 494 return vec3(Of<T>()); 495 } 496 497 /// @return the tint AST type for a 4-element vector of the C type `T`. 498 template <typename T> vec4()499 const ast::Vector* vec4() const { 500 return vec4(Of<T>()); 501 } 502 503 /// @param type matrix subtype 504 /// @param columns number of columns for the matrix 505 /// @param rows number of rows for the matrix 506 /// @return the tint AST type for a matrix of `type` mat(const ast::Type * type,uint32_t columns,uint32_t rows)507 const ast::Matrix* mat(const ast::Type* type, 508 uint32_t columns, 509 uint32_t rows) const { 510 return builder->create<ast::Matrix>(type, rows, columns); 511 } 512 513 /// @param source the Source of the node 514 /// @param type matrix subtype 515 /// @param columns number of columns for the matrix 516 /// @param rows number of rows for the matrix 517 /// @return the tint AST type for a matrix of `type` mat(const Source & source,const ast::Type * type,uint32_t columns,uint32_t rows)518 const ast::Matrix* mat(const Source& source, 519 const ast::Type* type, 520 uint32_t columns, 521 uint32_t rows) const { 522 return builder->create<ast::Matrix>(source, type, rows, columns); 523 } 524 525 /// @param type matrix subtype 526 /// @return the tint AST type for a 2x3 matrix of `type`. mat2x2(const ast::Type * type)527 const ast::Matrix* mat2x2(const ast::Type* type) const { 528 return mat(type, 2u, 2u); 529 } 530 531 /// @param type matrix subtype 532 /// @return the tint AST type for a 2x3 matrix of `type`. mat2x3(const ast::Type * type)533 const ast::Matrix* mat2x3(const ast::Type* type) const { 534 return mat(type, 2u, 3u); 535 } 536 537 /// @param type matrix subtype 538 /// @return the tint AST type for a 2x4 matrix of `type`. mat2x4(const ast::Type * type)539 const ast::Matrix* mat2x4(const ast::Type* type) const { 540 return mat(type, 2u, 4u); 541 } 542 543 /// @param type matrix subtype 544 /// @return the tint AST type for a 3x2 matrix of `type`. mat3x2(const ast::Type * type)545 const ast::Matrix* mat3x2(const ast::Type* type) const { 546 return mat(type, 3u, 2u); 547 } 548 549 /// @param type matrix subtype 550 /// @return the tint AST type for a 3x3 matrix of `type`. mat3x3(const ast::Type * type)551 const ast::Matrix* mat3x3(const ast::Type* type) const { 552 return mat(type, 3u, 3u); 553 } 554 555 /// @param type matrix subtype 556 /// @return the tint AST type for a 3x4 matrix of `type`. mat3x4(const ast::Type * type)557 const ast::Matrix* mat3x4(const ast::Type* type) const { 558 return mat(type, 3u, 4u); 559 } 560 561 /// @param type matrix subtype 562 /// @return the tint AST type for a 4x2 matrix of `type`. mat4x2(const ast::Type * type)563 const ast::Matrix* mat4x2(const ast::Type* type) const { 564 return mat(type, 4u, 2u); 565 } 566 567 /// @param type matrix subtype 568 /// @return the tint AST type for a 4x3 matrix of `type`. mat4x3(const ast::Type * type)569 const ast::Matrix* mat4x3(const ast::Type* type) const { 570 return mat(type, 4u, 3u); 571 } 572 573 /// @param type matrix subtype 574 /// @return the tint AST type for a 4x4 matrix of `type`. mat4x4(const ast::Type * type)575 const ast::Matrix* mat4x4(const ast::Type* type) const { 576 return mat(type, 4u, 4u); 577 } 578 579 /// @param columns number of columns for the matrix 580 /// @param rows number of rows for the matrix 581 /// @return the tint AST type for a matrix of `type` 582 template <typename T> mat(uint32_t columns,uint32_t rows)583 const ast::Matrix* mat(uint32_t columns, uint32_t rows) const { 584 return mat(Of<T>(), columns, rows); 585 } 586 587 /// @return the tint AST type for a 2x3 matrix of the C type `T`. 588 template <typename T> mat2x2()589 const ast::Matrix* mat2x2() const { 590 return mat2x2(Of<T>()); 591 } 592 593 /// @return the tint AST type for a 2x3 matrix of the C type `T`. 594 template <typename T> mat2x3()595 const ast::Matrix* mat2x3() const { 596 return mat2x3(Of<T>()); 597 } 598 599 /// @return the tint AST type for a 2x4 matrix of the C type `T`. 600 template <typename T> mat2x4()601 const ast::Matrix* mat2x4() const { 602 return mat2x4(Of<T>()); 603 } 604 605 /// @return the tint AST type for a 3x2 matrix of the C type `T`. 606 template <typename T> mat3x2()607 const ast::Matrix* mat3x2() const { 608 return mat3x2(Of<T>()); 609 } 610 611 /// @return the tint AST type for a 3x3 matrix of the C type `T`. 612 template <typename T> mat3x3()613 const ast::Matrix* mat3x3() const { 614 return mat3x3(Of<T>()); 615 } 616 617 /// @return the tint AST type for a 3x4 matrix of the C type `T`. 618 template <typename T> mat3x4()619 const ast::Matrix* mat3x4() const { 620 return mat3x4(Of<T>()); 621 } 622 623 /// @return the tint AST type for a 4x2 matrix of the C type `T`. 624 template <typename T> mat4x2()625 const ast::Matrix* mat4x2() const { 626 return mat4x2(Of<T>()); 627 } 628 629 /// @return the tint AST type for a 4x3 matrix of the C type `T`. 630 template <typename T> mat4x3()631 const ast::Matrix* mat4x3() const { 632 return mat4x3(Of<T>()); 633 } 634 635 /// @return the tint AST type for a 4x4 matrix of the C type `T`. 636 template <typename T> mat4x4()637 const ast::Matrix* mat4x4() const { 638 return mat4x4(Of<T>()); 639 } 640 641 /// @param subtype the array element type 642 /// @param n the array size. nullptr represents a runtime-array 643 /// @param decos the optional decorations for the array 644 /// @return the tint AST type for a array of size `n` of type `T` 645 template <typename EXPR = ast::Expression*> 646 const ast::Array* array(const ast::Type* subtype, 647 EXPR&& n = nullptr, 648 ast::DecorationList decos = {}) const { 649 return builder->create<ast::Array>( 650 subtype, builder->Expr(std::forward<EXPR>(n)), decos); 651 } 652 653 /// @param source the Source of the node 654 /// @param subtype the array element type 655 /// @param n the array size. nullptr represents a runtime-array 656 /// @param decos the optional decorations for the array 657 /// @return the tint AST type for a array of size `n` of type `T` 658 template <typename EXPR = ast::Expression*> 659 const ast::Array* array(const Source& source, 660 const ast::Type* subtype, 661 EXPR&& n = nullptr, 662 ast::DecorationList decos = {}) const { 663 return builder->create<ast::Array>( 664 source, subtype, builder->Expr(std::forward<EXPR>(n)), decos); 665 } 666 667 /// @param subtype the array element type 668 /// @param n the array size. nullptr represents a runtime-array 669 /// @param stride the array stride. 0 represents implicit stride 670 /// @return the tint AST type for a array of size `n` of type `T` 671 template <typename EXPR> array(const ast::Type * subtype,EXPR && n,uint32_t stride)672 const ast::Array* array(const ast::Type* subtype, 673 EXPR&& n, 674 uint32_t stride) const { 675 ast::DecorationList decos; 676 if (stride) { 677 decos.emplace_back(builder->create<ast::StrideDecoration>(stride)); 678 } 679 return array(subtype, std::forward<EXPR>(n), std::move(decos)); 680 } 681 682 /// @param source the Source of the node 683 /// @param subtype the array element type 684 /// @param n the array size. nullptr represents a runtime-array 685 /// @param stride the array stride. 0 represents implicit stride 686 /// @return the tint AST type for a array of size `n` of type `T` 687 template <typename EXPR> array(const Source & source,const ast::Type * subtype,EXPR && n,uint32_t stride)688 const ast::Array* array(const Source& source, 689 const ast::Type* subtype, 690 EXPR&& n, 691 uint32_t stride) const { 692 ast::DecorationList decos; 693 if (stride) { 694 decos.emplace_back(builder->create<ast::StrideDecoration>(stride)); 695 } 696 return array(source, subtype, std::forward<EXPR>(n), std::move(decos)); 697 } 698 699 /// @return the tint AST type for a runtime-sized array of type `T` 700 template <typename T> array()701 const ast::Array* array() const { 702 return array(Of<T>(), nullptr); 703 } 704 705 /// @return the tint AST type for an array of size `N` of type `T` 706 template <typename T, int N> array()707 const ast::Array* array() const { 708 return array(Of<T>(), builder->Expr(N)); 709 } 710 711 /// @param stride the array stride 712 /// @return the tint AST type for a runtime-sized array of type `T` 713 template <typename T> array(uint32_t stride)714 const ast::Array* array(uint32_t stride) const { 715 return array(Of<T>(), nullptr, stride); 716 } 717 718 /// @param stride the array stride 719 /// @return the tint AST type for an array of size `N` of type `T` 720 template <typename T, int N> array(uint32_t stride)721 const ast::Array* array(uint32_t stride) const { 722 return array(Of<T>(), builder->Expr(N), stride); 723 } 724 725 /// Creates a type name 726 /// @param name the name 727 /// @returns the type name 728 template <typename NAME> type_name(NAME && name)729 const ast::TypeName* type_name(NAME&& name) const { 730 return builder->create<ast::TypeName>( 731 builder->Sym(std::forward<NAME>(name))); 732 } 733 734 /// Creates a type name 735 /// @param source the Source of the node 736 /// @param name the name 737 /// @returns the type name 738 template <typename NAME> type_name(const Source & source,NAME && name)739 const ast::TypeName* type_name(const Source& source, NAME&& name) const { 740 return builder->create<ast::TypeName>( 741 source, builder->Sym(std::forward<NAME>(name))); 742 } 743 744 /// Creates an alias type 745 /// @param name the alias name 746 /// @param type the alias type 747 /// @returns the alias pointer 748 template <typename NAME> alias(NAME && name,const ast::Type * type)749 const ast::Alias* alias(NAME&& name, const ast::Type* type) const { 750 auto sym = builder->Sym(std::forward<NAME>(name)); 751 return builder->create<ast::Alias>(sym, type); 752 } 753 754 /// Creates an alias type 755 /// @param source the Source of the node 756 /// @param name the alias name 757 /// @param type the alias type 758 /// @returns the alias pointer 759 template <typename NAME> alias(const Source & source,NAME && name,const ast::Type * type)760 const ast::Alias* alias(const Source& source, 761 NAME&& name, 762 const ast::Type* type) const { 763 auto sym = builder->Sym(std::forward<NAME>(name)); 764 return builder->create<ast::Alias>(source, sym, type); 765 } 766 767 /// @param type the type of the pointer 768 /// @param storage_class the storage class of the pointer 769 /// @param access the optional access control of the pointer 770 /// @return the pointer to `type` with the given ast::StorageClass 771 const ast::Pointer* pointer( 772 const ast::Type* type, 773 ast::StorageClass storage_class, 774 ast::Access access = ast::Access::kUndefined) const { 775 return builder->create<ast::Pointer>(type, storage_class, access); 776 } 777 778 /// @param source the Source of the node 779 /// @param type the type of the pointer 780 /// @param storage_class the storage class of the pointer 781 /// @param access the optional access control of the pointer 782 /// @return the pointer to `type` with the given ast::StorageClass 783 const ast::Pointer* pointer( 784 const Source& source, 785 const ast::Type* type, 786 ast::StorageClass storage_class, 787 ast::Access access = ast::Access::kUndefined) const { 788 return builder->create<ast::Pointer>(source, type, storage_class, access); 789 } 790 791 /// @param storage_class the storage class of the pointer 792 /// @param access the optional access control of the pointer 793 /// @return the pointer to type `T` with the given ast::StorageClass. 794 template <typename T> 795 const ast::Pointer* pointer( 796 ast::StorageClass storage_class, 797 ast::Access access = ast::Access::kUndefined) const { 798 return pointer(Of<T>(), storage_class, access); 799 } 800 801 /// @param source the Source of the node 802 /// @param type the type of the atomic 803 /// @return the atomic to `type` atomic(const Source & source,const ast::Type * type)804 const ast::Atomic* atomic(const Source& source, 805 const ast::Type* type) const { 806 return builder->create<ast::Atomic>(source, type); 807 } 808 809 /// @param type the type of the atomic 810 /// @return the atomic to `type` atomic(const ast::Type * type)811 const ast::Atomic* atomic(const ast::Type* type) const { 812 return builder->create<ast::Atomic>(type); 813 } 814 815 /// @return the atomic to type `T` 816 template <typename T> atomic()817 const ast::Atomic* atomic() const { 818 return atomic(Of<T>()); 819 } 820 821 /// @param kind the kind of sampler 822 /// @returns the sampler sampler(ast::SamplerKind kind)823 const ast::Sampler* sampler(ast::SamplerKind kind) const { 824 return builder->create<ast::Sampler>(kind); 825 } 826 827 /// @param source the Source of the node 828 /// @param kind the kind of sampler 829 /// @returns the sampler sampler(const Source & source,ast::SamplerKind kind)830 const ast::Sampler* sampler(const Source& source, 831 ast::SamplerKind kind) const { 832 return builder->create<ast::Sampler>(source, kind); 833 } 834 835 /// @param dims the dimensionality of the texture 836 /// @returns the depth texture depth_texture(ast::TextureDimension dims)837 const ast::DepthTexture* depth_texture(ast::TextureDimension dims) const { 838 return builder->create<ast::DepthTexture>(dims); 839 } 840 841 /// @param source the Source of the node 842 /// @param dims the dimensionality of the texture 843 /// @returns the depth texture depth_texture(const Source & source,ast::TextureDimension dims)844 const ast::DepthTexture* depth_texture(const Source& source, 845 ast::TextureDimension dims) const { 846 return builder->create<ast::DepthTexture>(source, dims); 847 } 848 849 /// @param dims the dimensionality of the texture 850 /// @returns the multisampled depth texture depth_multisampled_texture(ast::TextureDimension dims)851 const ast::DepthMultisampledTexture* depth_multisampled_texture( 852 ast::TextureDimension dims) const { 853 return builder->create<ast::DepthMultisampledTexture>(dims); 854 } 855 856 /// @param source the Source of the node 857 /// @param dims the dimensionality of the texture 858 /// @returns the multisampled depth texture depth_multisampled_texture(const Source & source,ast::TextureDimension dims)859 const ast::DepthMultisampledTexture* depth_multisampled_texture( 860 const Source& source, 861 ast::TextureDimension dims) const { 862 return builder->create<ast::DepthMultisampledTexture>(source, dims); 863 } 864 865 /// @param dims the dimensionality of the texture 866 /// @param subtype the texture subtype. 867 /// @returns the sampled texture sampled_texture(ast::TextureDimension dims,const ast::Type * subtype)868 const ast::SampledTexture* sampled_texture(ast::TextureDimension dims, 869 const ast::Type* subtype) const { 870 return builder->create<ast::SampledTexture>(dims, subtype); 871 } 872 873 /// @param source the Source of the node 874 /// @param dims the dimensionality of the texture 875 /// @param subtype the texture subtype. 876 /// @returns the sampled texture sampled_texture(const Source & source,ast::TextureDimension dims,const ast::Type * subtype)877 const ast::SampledTexture* sampled_texture(const Source& source, 878 ast::TextureDimension dims, 879 const ast::Type* subtype) const { 880 return builder->create<ast::SampledTexture>(source, dims, subtype); 881 } 882 883 /// @param dims the dimensionality of the texture 884 /// @param subtype the texture subtype. 885 /// @returns the multisampled texture multisampled_texture(ast::TextureDimension dims,const ast::Type * subtype)886 const ast::MultisampledTexture* multisampled_texture( 887 ast::TextureDimension dims, 888 const ast::Type* subtype) const { 889 return builder->create<ast::MultisampledTexture>(dims, subtype); 890 } 891 892 /// @param source the Source of the node 893 /// @param dims the dimensionality of the texture 894 /// @param subtype the texture subtype. 895 /// @returns the multisampled texture multisampled_texture(const Source & source,ast::TextureDimension dims,const ast::Type * subtype)896 const ast::MultisampledTexture* multisampled_texture( 897 const Source& source, 898 ast::TextureDimension dims, 899 const ast::Type* subtype) const { 900 return builder->create<ast::MultisampledTexture>(source, dims, subtype); 901 } 902 903 /// @param dims the dimensionality of the texture 904 /// @param format the image format of the texture 905 /// @param access the access control of the texture 906 /// @returns the storage texture storage_texture(ast::TextureDimension dims,ast::ImageFormat format,ast::Access access)907 const ast::StorageTexture* storage_texture(ast::TextureDimension dims, 908 ast::ImageFormat format, 909 ast::Access access) const { 910 auto* subtype = ast::StorageTexture::SubtypeFor(format, *builder); 911 return builder->create<ast::StorageTexture>(dims, format, subtype, 912 access); 913 } 914 915 /// @param source the Source of the node 916 /// @param dims the dimensionality of the texture 917 /// @param format the image format of the texture 918 /// @param access the access control of the texture 919 /// @returns the storage texture storage_texture(const Source & source,ast::TextureDimension dims,ast::ImageFormat format,ast::Access access)920 const ast::StorageTexture* storage_texture(const Source& source, 921 ast::TextureDimension dims, 922 ast::ImageFormat format, 923 ast::Access access) const { 924 auto* subtype = ast::StorageTexture::SubtypeFor(format, *builder); 925 return builder->create<ast::StorageTexture>(source, dims, format, subtype, 926 access); 927 } 928 929 /// @returns the external texture external_texture()930 const ast::ExternalTexture* external_texture() const { 931 return builder->create<ast::ExternalTexture>(); 932 } 933 934 /// @param source the Source of the node 935 /// @returns the external texture external_texture(const Source & source)936 const ast::ExternalTexture* external_texture(const Source& source) const { 937 return builder->create<ast::ExternalTexture>(source); 938 } 939 940 /// Constructs a TypeName for the type declaration. 941 /// @param type the type 942 /// @return either type or a pointer to a new ast::TypeName 943 const ast::TypeName* Of(const ast::TypeDecl* type) const; 944 945 /// The ProgramBuilder 946 ProgramBuilder* const builder; 947 948 private: 949 /// CToAST<T> is specialized for various `T` types and each specialization 950 /// contains a single static `get()` method for obtaining the corresponding 951 /// AST type for the C type `T`. 952 /// `get()` has the signature: 953 /// `static const ast::Type* get(Types* t)` 954 template <typename T> 955 struct CToAST {}; 956 }; 957 958 ////////////////////////////////////////////////////////////////////////////// 959 // AST helper methods 960 ////////////////////////////////////////////////////////////////////////////// 961 962 /// @return a new unnamed symbol Sym()963 Symbol Sym() { return Symbols().New(); } 964 965 /// @param name the symbol string 966 /// @return a Symbol with the given name Sym(const std::string & name)967 Symbol Sym(const std::string& name) { return Symbols().Register(name); } 968 969 /// @param sym the symbol 970 /// @return `sym` Sym(Symbol sym)971 Symbol Sym(Symbol sym) { return sym; } 972 973 /// @param expr the expression 974 /// @return expr 975 template <typename T> Expr(T * expr)976 traits::EnableIfIsType<T, ast::Expression>* Expr(T* expr) { 977 return expr; 978 } 979 980 /// Passthrough for nullptr 981 /// @return nullptr Expr(std::nullptr_t)982 const ast::IdentifierExpression* Expr(std::nullptr_t) { return nullptr; } 983 984 /// @param source the source information 985 /// @param symbol the identifier symbol 986 /// @return an ast::IdentifierExpression with the given symbol Expr(const Source & source,Symbol symbol)987 const ast::IdentifierExpression* Expr(const Source& source, Symbol symbol) { 988 return create<ast::IdentifierExpression>(source, symbol); 989 } 990 991 /// @param symbol the identifier symbol 992 /// @return an ast::IdentifierExpression with the given symbol Expr(Symbol symbol)993 const ast::IdentifierExpression* Expr(Symbol symbol) { 994 return create<ast::IdentifierExpression>(symbol); 995 } 996 997 /// @param source the source information 998 /// @param variable the AST variable 999 /// @return an ast::IdentifierExpression with the variable's symbol Expr(const Source & source,const ast::Variable * variable)1000 const ast::IdentifierExpression* Expr(const Source& source, 1001 const ast::Variable* variable) { 1002 return create<ast::IdentifierExpression>(source, variable->symbol); 1003 } 1004 1005 /// @param variable the AST variable 1006 /// @return an ast::IdentifierExpression with the variable's symbol Expr(const ast::Variable * variable)1007 const ast::IdentifierExpression* Expr(const ast::Variable* variable) { 1008 return create<ast::IdentifierExpression>(variable->symbol); 1009 } 1010 1011 /// @param source the source information 1012 /// @param name the identifier name 1013 /// @return an ast::IdentifierExpression with the given name Expr(const Source & source,const char * name)1014 const ast::IdentifierExpression* Expr(const Source& source, 1015 const char* name) { 1016 return create<ast::IdentifierExpression>(source, Symbols().Register(name)); 1017 } 1018 1019 /// @param name the identifier name 1020 /// @return an ast::IdentifierExpression with the given name Expr(const char * name)1021 const ast::IdentifierExpression* Expr(const char* name) { 1022 return create<ast::IdentifierExpression>(Symbols().Register(name)); 1023 } 1024 1025 /// @param source the source information 1026 /// @param name the identifier name 1027 /// @return an ast::IdentifierExpression with the given name Expr(const Source & source,const std::string & name)1028 const ast::IdentifierExpression* Expr(const Source& source, 1029 const std::string& name) { 1030 return create<ast::IdentifierExpression>(source, Symbols().Register(name)); 1031 } 1032 1033 /// @param name the identifier name 1034 /// @return an ast::IdentifierExpression with the given name Expr(const std::string & name)1035 const ast::IdentifierExpression* Expr(const std::string& name) { 1036 return create<ast::IdentifierExpression>(Symbols().Register(name)); 1037 } 1038 1039 /// @param source the source information 1040 /// @param value the boolean value 1041 /// @return a Scalar constructor for the given value Expr(const Source & source,bool value)1042 const ast::BoolLiteralExpression* Expr(const Source& source, bool value) { 1043 return create<ast::BoolLiteralExpression>(source, value); 1044 } 1045 1046 /// @param value the boolean value 1047 /// @return a Scalar constructor for the given value Expr(bool value)1048 const ast::BoolLiteralExpression* Expr(bool value) { 1049 return create<ast::BoolLiteralExpression>(value); 1050 } 1051 1052 /// @param source the source information 1053 /// @param value the float value 1054 /// @return a Scalar constructor for the given value Expr(const Source & source,f32 value)1055 const ast::FloatLiteralExpression* Expr(const Source& source, f32 value) { 1056 return create<ast::FloatLiteralExpression>(source, value); 1057 } 1058 1059 /// @param value the float value 1060 /// @return a Scalar constructor for the given value Expr(f32 value)1061 const ast::FloatLiteralExpression* Expr(f32 value) { 1062 return create<ast::FloatLiteralExpression>(value); 1063 } 1064 1065 /// @param source the source information 1066 /// @param value the integer value 1067 /// @return a Scalar constructor for the given value Expr(const Source & source,i32 value)1068 const ast::SintLiteralExpression* Expr(const Source& source, i32 value) { 1069 return create<ast::SintLiteralExpression>(source, value); 1070 } 1071 1072 /// @param value the integer value 1073 /// @return a Scalar constructor for the given value Expr(i32 value)1074 const ast::SintLiteralExpression* Expr(i32 value) { 1075 return create<ast::SintLiteralExpression>(value); 1076 } 1077 1078 /// @param source the source information 1079 /// @param value the unsigned int value 1080 /// @return a Scalar constructor for the given value Expr(const Source & source,u32 value)1081 const ast::UintLiteralExpression* Expr(const Source& source, u32 value) { 1082 return create<ast::UintLiteralExpression>(source, value); 1083 } 1084 1085 /// @param value the unsigned int value 1086 /// @return a Scalar constructor for the given value Expr(u32 value)1087 const ast::UintLiteralExpression* Expr(u32 value) { 1088 return create<ast::UintLiteralExpression>(value); 1089 } 1090 1091 /// Converts `arg` to an `ast::Expression` using `Expr()`, then appends it to 1092 /// `list`. 1093 /// @param list the list to append too 1094 /// @param arg the arg to create 1095 template <typename ARG> Append(ast::ExpressionList & list,ARG && arg)1096 void Append(ast::ExpressionList& list, ARG&& arg) { 1097 list.emplace_back(Expr(std::forward<ARG>(arg))); 1098 } 1099 1100 /// Converts `arg0` and `args` to `ast::Expression`s using `Expr()`, 1101 /// then appends them to `list`. 1102 /// @param list the list to append too 1103 /// @param arg0 the first argument 1104 /// @param args the rest of the arguments 1105 template <typename ARG0, typename... ARGS> Append(ast::ExpressionList & list,ARG0 && arg0,ARGS &&...args)1106 void Append(ast::ExpressionList& list, ARG0&& arg0, ARGS&&... args) { 1107 Append(list, std::forward<ARG0>(arg0)); 1108 Append(list, std::forward<ARGS>(args)...); 1109 } 1110 1111 /// @return an empty list of expressions ExprList()1112 ast::ExpressionList ExprList() { return {}; } 1113 1114 /// @param args the list of expressions 1115 /// @return the list of expressions converted to `ast::Expression`s using 1116 /// `Expr()`, 1117 template <typename... ARGS> ExprList(ARGS &&...args)1118 ast::ExpressionList ExprList(ARGS&&... args) { 1119 ast::ExpressionList list; 1120 list.reserve(sizeof...(args)); 1121 Append(list, std::forward<ARGS>(args)...); 1122 return list; 1123 } 1124 1125 /// @param list the list of expressions 1126 /// @return `list` ExprList(ast::ExpressionList list)1127 ast::ExpressionList ExprList(ast::ExpressionList list) { return list; } 1128 1129 /// @param args the arguments for the type constructor 1130 /// @return an `ast::CallExpression` of type `ty`, with the values 1131 /// of `args` converted to `ast::Expression`s using `Expr()` 1132 template <typename T, typename... ARGS> Construct(ARGS &&...args)1133 const ast::CallExpression* Construct(ARGS&&... args) { 1134 return Construct(ty.Of<T>(), std::forward<ARGS>(args)...); 1135 } 1136 1137 /// @param type the type to construct 1138 /// @param args the arguments for the constructor 1139 /// @return an `ast::CallExpression` of `type` constructed with the 1140 /// values `args`. 1141 template <typename... ARGS> Construct(const ast::Type * type,ARGS &&...args)1142 const ast::CallExpression* Construct(const ast::Type* type, ARGS&&... args) { 1143 return Construct(source_, type, std::forward<ARGS>(args)...); 1144 } 1145 1146 /// @param source the source information 1147 /// @param type the type to construct 1148 /// @param args the arguments for the constructor 1149 /// @return an `ast::CallExpression` of `type` constructed with the 1150 /// values `args`. 1151 template <typename... ARGS> Construct(const Source & source,const ast::Type * type,ARGS &&...args)1152 const ast::CallExpression* Construct(const Source& source, 1153 const ast::Type* type, 1154 ARGS&&... args) { 1155 return create<ast::CallExpression>(source, type, 1156 ExprList(std::forward<ARGS>(args)...)); 1157 } 1158 1159 /// @param expr the expression for the bitcast 1160 /// @return an `ast::BitcastExpression` of type `ty`, with the values of 1161 /// `expr` converted to `ast::Expression`s using `Expr()` 1162 template <typename T, typename EXPR> Bitcast(EXPR && expr)1163 const ast::BitcastExpression* Bitcast(EXPR&& expr) { 1164 return Bitcast(ty.Of<T>(), std::forward<EXPR>(expr)); 1165 } 1166 1167 /// @param type the type to cast to 1168 /// @param expr the expression for the bitcast 1169 /// @return an `ast::BitcastExpression` of `type` constructed with the values 1170 /// `expr`. 1171 template <typename EXPR> Bitcast(const ast::Type * type,EXPR && expr)1172 const ast::BitcastExpression* Bitcast(const ast::Type* type, EXPR&& expr) { 1173 return create<ast::BitcastExpression>(type, Expr(std::forward<EXPR>(expr))); 1174 } 1175 1176 /// @param source the source information 1177 /// @param type the type to cast to 1178 /// @param expr the expression for the bitcast 1179 /// @return an `ast::BitcastExpression` of `type` constructed with the values 1180 /// `expr`. 1181 template <typename EXPR> Bitcast(const Source & source,const ast::Type * type,EXPR && expr)1182 const ast::BitcastExpression* Bitcast(const Source& source, 1183 const ast::Type* type, 1184 EXPR&& expr) { 1185 return create<ast::BitcastExpression>(source, type, 1186 Expr(std::forward<EXPR>(expr))); 1187 } 1188 1189 /// @param args the arguments for the vector constructor 1190 /// @param type the vector type 1191 /// @param size the vector size 1192 /// @return an `ast::CallExpression` of a `size`-element vector of 1193 /// type `type`, constructed with the values `args`. 1194 template <typename... ARGS> vec(const ast::Type * type,uint32_t size,ARGS &&...args)1195 const ast::CallExpression* vec(const ast::Type* type, 1196 uint32_t size, 1197 ARGS&&... args) { 1198 return Construct(ty.vec(type, size), std::forward<ARGS>(args)...); 1199 } 1200 1201 /// @param args the arguments for the vector constructor 1202 /// @return an `ast::CallExpression` of a 2-element vector of type 1203 /// `T`, constructed with the values `args`. 1204 template <typename T, typename... ARGS> vec2(ARGS &&...args)1205 const ast::CallExpression* vec2(ARGS&&... args) { 1206 return Construct(ty.vec2<T>(), std::forward<ARGS>(args)...); 1207 } 1208 1209 /// @param args the arguments for the vector constructor 1210 /// @return an `ast::CallExpression` of a 3-element vector of type 1211 /// `T`, constructed with the values `args`. 1212 template <typename T, typename... ARGS> vec3(ARGS &&...args)1213 const ast::CallExpression* vec3(ARGS&&... args) { 1214 return Construct(ty.vec3<T>(), std::forward<ARGS>(args)...); 1215 } 1216 1217 /// @param args the arguments for the vector constructor 1218 /// @return an `ast::CallExpression` of a 4-element vector of type 1219 /// `T`, constructed with the values `args`. 1220 template <typename T, typename... ARGS> vec4(ARGS &&...args)1221 const ast::CallExpression* vec4(ARGS&&... args) { 1222 return Construct(ty.vec4<T>(), std::forward<ARGS>(args)...); 1223 } 1224 1225 /// @param args the arguments for the matrix constructor 1226 /// @return an `ast::CallExpression` of a 2x2 matrix of type 1227 /// `T`, constructed with the values `args`. 1228 template <typename T, typename... ARGS> mat2x2(ARGS &&...args)1229 const ast::CallExpression* mat2x2(ARGS&&... args) { 1230 return Construct(ty.mat2x2<T>(), std::forward<ARGS>(args)...); 1231 } 1232 1233 /// @param args the arguments for the matrix constructor 1234 /// @return an `ast::CallExpression` of a 2x3 matrix of type 1235 /// `T`, constructed with the values `args`. 1236 template <typename T, typename... ARGS> mat2x3(ARGS &&...args)1237 const ast::CallExpression* mat2x3(ARGS&&... args) { 1238 return Construct(ty.mat2x3<T>(), std::forward<ARGS>(args)...); 1239 } 1240 1241 /// @param args the arguments for the matrix constructor 1242 /// @return an `ast::CallExpression` of a 2x4 matrix of type 1243 /// `T`, constructed with the values `args`. 1244 template <typename T, typename... ARGS> mat2x4(ARGS &&...args)1245 const ast::CallExpression* mat2x4(ARGS&&... args) { 1246 return Construct(ty.mat2x4<T>(), std::forward<ARGS>(args)...); 1247 } 1248 1249 /// @param args the arguments for the matrix constructor 1250 /// @return an `ast::CallExpression` of a 3x2 matrix of type 1251 /// `T`, constructed with the values `args`. 1252 template <typename T, typename... ARGS> mat3x2(ARGS &&...args)1253 const ast::CallExpression* mat3x2(ARGS&&... args) { 1254 return Construct(ty.mat3x2<T>(), std::forward<ARGS>(args)...); 1255 } 1256 1257 /// @param args the arguments for the matrix constructor 1258 /// @return an `ast::CallExpression` of a 3x3 matrix of type 1259 /// `T`, constructed with the values `args`. 1260 template <typename T, typename... ARGS> mat3x3(ARGS &&...args)1261 const ast::CallExpression* mat3x3(ARGS&&... args) { 1262 return Construct(ty.mat3x3<T>(), std::forward<ARGS>(args)...); 1263 } 1264 1265 /// @param args the arguments for the matrix constructor 1266 /// @return an `ast::CallExpression` of a 3x4 matrix of type 1267 /// `T`, constructed with the values `args`. 1268 template <typename T, typename... ARGS> mat3x4(ARGS &&...args)1269 const ast::CallExpression* mat3x4(ARGS&&... args) { 1270 return Construct(ty.mat3x4<T>(), std::forward<ARGS>(args)...); 1271 } 1272 1273 /// @param args the arguments for the matrix constructor 1274 /// @return an `ast::CallExpression` of a 4x2 matrix of type 1275 /// `T`, constructed with the values `args`. 1276 template <typename T, typename... ARGS> mat4x2(ARGS &&...args)1277 const ast::CallExpression* mat4x2(ARGS&&... args) { 1278 return Construct(ty.mat4x2<T>(), std::forward<ARGS>(args)...); 1279 } 1280 1281 /// @param args the arguments for the matrix constructor 1282 /// @return an `ast::CallExpression` of a 4x3 matrix of type 1283 /// `T`, constructed with the values `args`. 1284 template <typename T, typename... ARGS> mat4x3(ARGS &&...args)1285 const ast::CallExpression* mat4x3(ARGS&&... args) { 1286 return Construct(ty.mat4x3<T>(), std::forward<ARGS>(args)...); 1287 } 1288 1289 /// @param args the arguments for the matrix constructor 1290 /// @return an `ast::CallExpression` of a 4x4 matrix of type 1291 /// `T`, constructed with the values `args`. 1292 template <typename T, typename... ARGS> mat4x4(ARGS &&...args)1293 const ast::CallExpression* mat4x4(ARGS&&... args) { 1294 return Construct(ty.mat4x4<T>(), std::forward<ARGS>(args)...); 1295 } 1296 1297 /// @param args the arguments for the array constructor 1298 /// @return an `ast::CallExpression` of an array with element type 1299 /// `T` and size `N`, constructed with the values `args`. 1300 template <typename T, int N, typename... ARGS> array(ARGS &&...args)1301 const ast::CallExpression* array(ARGS&&... args) { 1302 return Construct(ty.array<T, N>(), std::forward<ARGS>(args)...); 1303 } 1304 1305 /// @param subtype the array element type 1306 /// @param n the array size. nullptr represents a runtime-array. 1307 /// @param args the arguments for the array constructor 1308 /// @return an `ast::CallExpression` of an array with element type 1309 /// `subtype`, constructed with the values `args`. 1310 template <typename EXPR, typename... ARGS> array(const ast::Type * subtype,EXPR && n,ARGS &&...args)1311 const ast::CallExpression* array(const ast::Type* subtype, 1312 EXPR&& n, 1313 ARGS&&... args) { 1314 return Construct(ty.array(subtype, std::forward<EXPR>(n)), 1315 std::forward<ARGS>(args)...); 1316 } 1317 1318 /// @param name the variable name 1319 /// @param type the variable type 1320 /// @param optional the optional variable settings. 1321 /// Can be any of the following, in any order: 1322 /// * ast::StorageClass - specifies the variable storage class 1323 /// * ast::Access - specifies the variable's access control 1324 /// * ast::Expression* - specifies the variable's initializer expression 1325 /// * ast::DecorationList - specifies the variable's decorations 1326 /// Note that repeated arguments of the same type will use the last argument's 1327 /// value. 1328 /// @returns a `ast::Variable` with the given name, type and additional 1329 /// options 1330 template <typename NAME, typename... OPTIONAL> Var(NAME && name,const ast::Type * type,OPTIONAL &&...optional)1331 const ast::Variable* Var(NAME&& name, 1332 const ast::Type* type, 1333 OPTIONAL&&... optional) { 1334 VarOptionals opts(std::forward<OPTIONAL>(optional)...); 1335 return create<ast::Variable>(Sym(std::forward<NAME>(name)), opts.storage, 1336 opts.access, type, false, opts.constructor, 1337 std::move(opts.decorations)); 1338 } 1339 1340 /// @param source the variable source 1341 /// @param name the variable name 1342 /// @param type the variable type 1343 /// @param optional the optional variable settings. 1344 /// Can be any of the following, in any order: 1345 /// * ast::StorageClass - specifies the variable storage class 1346 /// * ast::Access - specifies the variable's access control 1347 /// * ast::Expression* - specifies the variable's initializer expression 1348 /// * ast::DecorationList - specifies the variable's decorations 1349 /// Note that repeated arguments of the same type will use the last argument's 1350 /// value. 1351 /// @returns a `ast::Variable` with the given name, storage and type 1352 template <typename NAME, typename... OPTIONAL> Var(const Source & source,NAME && name,const ast::Type * type,OPTIONAL &&...optional)1353 const ast::Variable* Var(const Source& source, 1354 NAME&& name, 1355 const ast::Type* type, 1356 OPTIONAL&&... optional) { 1357 VarOptionals opts(std::forward<OPTIONAL>(optional)...); 1358 return create<ast::Variable>(source, Sym(std::forward<NAME>(name)), 1359 opts.storage, opts.access, type, false, 1360 opts.constructor, std::move(opts.decorations)); 1361 } 1362 1363 /// @param name the variable name 1364 /// @param type the variable type 1365 /// @param constructor constructor expression 1366 /// @param decorations optional variable decorations 1367 /// @returns a constant `ast::Variable` with the given name and type 1368 template <typename NAME> 1369 const ast::Variable* Const(NAME&& name, 1370 const ast::Type* type, 1371 const ast::Expression* constructor, 1372 ast::DecorationList decorations = {}) { 1373 return create<ast::Variable>( 1374 Sym(std::forward<NAME>(name)), ast::StorageClass::kNone, 1375 ast::Access::kUndefined, type, true, constructor, decorations); 1376 } 1377 1378 /// @param source the variable source 1379 /// @param name the variable name 1380 /// @param type the variable type 1381 /// @param constructor constructor expression 1382 /// @param decorations optional variable decorations 1383 /// @returns a constant `ast::Variable` with the given name and type 1384 template <typename NAME> 1385 const ast::Variable* Const(const Source& source, 1386 NAME&& name, 1387 const ast::Type* type, 1388 const ast::Expression* constructor, 1389 ast::DecorationList decorations = {}) { 1390 return create<ast::Variable>( 1391 source, Sym(std::forward<NAME>(name)), ast::StorageClass::kNone, 1392 ast::Access::kUndefined, type, true, constructor, decorations); 1393 } 1394 1395 /// @param name the parameter name 1396 /// @param type the parameter type 1397 /// @param decorations optional parameter decorations 1398 /// @returns a constant `ast::Variable` with the given name and type 1399 template <typename NAME> 1400 const ast::Variable* Param(NAME&& name, 1401 const ast::Type* type, 1402 ast::DecorationList decorations = {}) { 1403 return create<ast::Variable>( 1404 Sym(std::forward<NAME>(name)), ast::StorageClass::kNone, 1405 ast::Access::kUndefined, type, true, nullptr, decorations); 1406 } 1407 1408 /// @param source the parameter source 1409 /// @param name the parameter name 1410 /// @param type the parameter type 1411 /// @param decorations optional parameter decorations 1412 /// @returns a constant `ast::Variable` with the given name and type 1413 template <typename NAME> 1414 const ast::Variable* Param(const Source& source, 1415 NAME&& name, 1416 const ast::Type* type, 1417 ast::DecorationList decorations = {}) { 1418 return create<ast::Variable>( 1419 source, Sym(std::forward<NAME>(name)), ast::StorageClass::kNone, 1420 ast::Access::kUndefined, type, true, nullptr, decorations); 1421 } 1422 1423 /// @param name the variable name 1424 /// @param type the variable type 1425 /// @param optional the optional variable settings. 1426 /// Can be any of the following, in any order: 1427 /// * ast::StorageClass - specifies the variable storage class 1428 /// * ast::Access - specifies the variable's access control 1429 /// * ast::Expression* - specifies the variable's initializer expression 1430 /// * ast::DecorationList - specifies the variable's decorations 1431 /// Note that repeated arguments of the same type will use the last argument's 1432 /// value. 1433 /// @returns a new `ast::Variable`, which is automatically registered as a 1434 /// global variable with the ast::Module. 1435 template <typename NAME, 1436 typename... OPTIONAL, 1437 typename = DisableIfSource<NAME>> Global(NAME && name,const ast::Type * type,OPTIONAL &&...optional)1438 const ast::Variable* Global(NAME&& name, 1439 const ast::Type* type, 1440 OPTIONAL&&... optional) { 1441 auto* var = Var(std::forward<NAME>(name), type, 1442 std::forward<OPTIONAL>(optional)...); 1443 AST().AddGlobalVariable(var); 1444 return var; 1445 } 1446 1447 /// @param source the variable source 1448 /// @param name the variable name 1449 /// @param type the variable type 1450 /// @param optional the optional variable settings. 1451 /// Can be any of the following, in any order: 1452 /// * ast::StorageClass - specifies the variable storage class 1453 /// * ast::Access - specifies the variable's access control 1454 /// * ast::Expression* - specifies the variable's initializer expression 1455 /// * ast::DecorationList - specifies the variable's decorations 1456 /// Note that repeated arguments of the same type will use the last argument's 1457 /// value. 1458 /// @returns a new `ast::Variable`, which is automatically registered as a 1459 /// global variable with the ast::Module. 1460 template <typename NAME, typename... OPTIONAL> Global(const Source & source,NAME && name,const ast::Type * type,OPTIONAL &&...optional)1461 const ast::Variable* Global(const Source& source, 1462 NAME&& name, 1463 const ast::Type* type, 1464 OPTIONAL&&... optional) { 1465 auto* var = Var(source, std::forward<NAME>(name), type, 1466 std::forward<OPTIONAL>(optional)...); 1467 AST().AddGlobalVariable(var); 1468 return var; 1469 } 1470 1471 /// @param name the variable name 1472 /// @param type the variable type 1473 /// @param constructor constructor expression 1474 /// @param decorations optional variable decorations 1475 /// @returns a const `ast::Variable` constructed by calling Var() with the 1476 /// arguments of `args`, which is automatically registered as a global 1477 /// variable with the ast::Module. 1478 template <typename NAME> 1479 const ast::Variable* GlobalConst(NAME&& name, 1480 const ast::Type* type, 1481 const ast::Expression* constructor, 1482 ast::DecorationList decorations = {}) { 1483 auto* var = Const(std::forward<NAME>(name), type, constructor, 1484 std::move(decorations)); 1485 AST().AddGlobalVariable(var); 1486 return var; 1487 } 1488 1489 /// @param source the variable source 1490 /// @param name the variable name 1491 /// @param type the variable type 1492 /// @param constructor constructor expression 1493 /// @param decorations optional variable decorations 1494 /// @returns a const `ast::Variable` constructed by calling Var() with the 1495 /// arguments of `args`, which is automatically registered as a global 1496 /// variable with the ast::Module. 1497 template <typename NAME> 1498 const ast::Variable* GlobalConst(const Source& source, 1499 NAME&& name, 1500 const ast::Type* type, 1501 const ast::Expression* constructor, 1502 ast::DecorationList decorations = {}) { 1503 auto* var = Const(source, std::forward<NAME>(name), type, constructor, 1504 std::move(decorations)); 1505 AST().AddGlobalVariable(var); 1506 return var; 1507 } 1508 1509 /// @param source the source information 1510 /// @param expr the expression to take the address of 1511 /// @return an ast::UnaryOpExpression that takes the address of `expr` 1512 template <typename EXPR> AddressOf(const Source & source,EXPR && expr)1513 const ast::UnaryOpExpression* AddressOf(const Source& source, EXPR&& expr) { 1514 return create<ast::UnaryOpExpression>(source, ast::UnaryOp::kAddressOf, 1515 Expr(std::forward<EXPR>(expr))); 1516 } 1517 1518 /// @param expr the expression to take the address of 1519 /// @return an ast::UnaryOpExpression that takes the address of `expr` 1520 template <typename EXPR> AddressOf(EXPR && expr)1521 const ast::UnaryOpExpression* AddressOf(EXPR&& expr) { 1522 return create<ast::UnaryOpExpression>(ast::UnaryOp::kAddressOf, 1523 Expr(std::forward<EXPR>(expr))); 1524 } 1525 1526 /// @param source the source information 1527 /// @param expr the expression to perform an indirection on 1528 /// @return an ast::UnaryOpExpression that dereferences the pointer `expr` 1529 template <typename EXPR> Deref(const Source & source,EXPR && expr)1530 const ast::UnaryOpExpression* Deref(const Source& source, EXPR&& expr) { 1531 return create<ast::UnaryOpExpression>(source, ast::UnaryOp::kIndirection, 1532 Expr(std::forward<EXPR>(expr))); 1533 } 1534 1535 /// @param expr the expression to perform an indirection on 1536 /// @return an ast::UnaryOpExpression that dereferences the pointer `expr` 1537 template <typename EXPR> Deref(EXPR && expr)1538 const ast::UnaryOpExpression* Deref(EXPR&& expr) { 1539 return create<ast::UnaryOpExpression>(ast::UnaryOp::kIndirection, 1540 Expr(std::forward<EXPR>(expr))); 1541 } 1542 1543 /// @param source the source information 1544 /// @param func the function name 1545 /// @param args the function call arguments 1546 /// @returns a `ast::CallExpression` to the function `func`, with the 1547 /// arguments of `args` converted to `ast::Expression`s using `Expr()`. 1548 template <typename NAME, typename... ARGS> Call(const Source & source,NAME && func,ARGS &&...args)1549 const ast::CallExpression* Call(const Source& source, 1550 NAME&& func, 1551 ARGS&&... args) { 1552 return create<ast::CallExpression>(source, Expr(func), 1553 ExprList(std::forward<ARGS>(args)...)); 1554 } 1555 1556 /// @param func the function name 1557 /// @param args the function call arguments 1558 /// @returns a `ast::CallExpression` to the function `func`, with the 1559 /// arguments of `args` converted to `ast::Expression`s using `Expr()`. 1560 template <typename NAME, typename... ARGS, typename = DisableIfSource<NAME>> Call(NAME && func,ARGS &&...args)1561 const ast::CallExpression* Call(NAME&& func, ARGS&&... args) { 1562 return create<ast::CallExpression>(Expr(func), 1563 ExprList(std::forward<ARGS>(args)...)); 1564 } 1565 1566 /// @param source the source information 1567 /// @param call the call expression to wrap in a call statement 1568 /// @returns a `ast::CallStatement` for the given call expression CallStmt(const Source & source,const ast::CallExpression * call)1569 const ast::CallStatement* CallStmt(const Source& source, 1570 const ast::CallExpression* call) { 1571 return create<ast::CallStatement>(source, call); 1572 } 1573 1574 /// @param call the call expression to wrap in a call statement 1575 /// @returns a `ast::CallStatement` for the given call expression CallStmt(const ast::CallExpression * call)1576 const ast::CallStatement* CallStmt(const ast::CallExpression* call) { 1577 return create<ast::CallStatement>(call); 1578 } 1579 1580 /// @param source the source information 1581 /// @returns a `ast::PhonyExpression` Phony(const Source & source)1582 const ast::PhonyExpression* Phony(const Source& source) { 1583 return create<ast::PhonyExpression>(source); 1584 } 1585 1586 /// @returns a `ast::PhonyExpression` Phony()1587 const ast::PhonyExpression* Phony() { return create<ast::PhonyExpression>(); } 1588 1589 /// @param expr the expression to ignore 1590 /// @returns a `ast::AssignmentStatement` that assigns 'expr' to the phony 1591 /// (underscore) variable. 1592 template <typename EXPR> Ignore(EXPR && expr)1593 const ast::AssignmentStatement* Ignore(EXPR&& expr) { 1594 return create<ast::AssignmentStatement>(Phony(), Expr(expr)); 1595 } 1596 1597 /// @param lhs the left hand argument to the addition operation 1598 /// @param rhs the right hand argument to the addition operation 1599 /// @returns a `ast::BinaryExpression` summing the arguments `lhs` and `rhs` 1600 template <typename LHS, typename RHS> Add(LHS && lhs,RHS && rhs)1601 const ast::BinaryExpression* Add(LHS&& lhs, RHS&& rhs) { 1602 return create<ast::BinaryExpression>(ast::BinaryOp::kAdd, 1603 Expr(std::forward<LHS>(lhs)), 1604 Expr(std::forward<RHS>(rhs))); 1605 } 1606 1607 /// @param lhs the left hand argument to the and operation 1608 /// @param rhs the right hand argument to the and operation 1609 /// @returns a `ast::BinaryExpression` bitwise anding `lhs` and `rhs` 1610 template <typename LHS, typename RHS> And(LHS && lhs,RHS && rhs)1611 const ast::BinaryExpression* And(LHS&& lhs, RHS&& rhs) { 1612 return create<ast::BinaryExpression>(ast::BinaryOp::kAnd, 1613 Expr(std::forward<LHS>(lhs)), 1614 Expr(std::forward<RHS>(rhs))); 1615 } 1616 1617 /// @param lhs the left hand argument to the or operation 1618 /// @param rhs the right hand argument to the or operation 1619 /// @returns a `ast::BinaryExpression` bitwise or-ing `lhs` and `rhs` 1620 template <typename LHS, typename RHS> Or(LHS && lhs,RHS && rhs)1621 const ast::BinaryExpression* Or(LHS&& lhs, RHS&& rhs) { 1622 return create<ast::BinaryExpression>(ast::BinaryOp::kOr, 1623 Expr(std::forward<LHS>(lhs)), 1624 Expr(std::forward<RHS>(rhs))); 1625 } 1626 1627 /// @param lhs the left hand argument to the subtraction operation 1628 /// @param rhs the right hand argument to the subtraction operation 1629 /// @returns a `ast::BinaryExpression` subtracting `rhs` from `lhs` 1630 template <typename LHS, typename RHS> Sub(LHS && lhs,RHS && rhs)1631 const ast::BinaryExpression* Sub(LHS&& lhs, RHS&& rhs) { 1632 return create<ast::BinaryExpression>(ast::BinaryOp::kSubtract, 1633 Expr(std::forward<LHS>(lhs)), 1634 Expr(std::forward<RHS>(rhs))); 1635 } 1636 1637 /// @param lhs the left hand argument to the multiplication operation 1638 /// @param rhs the right hand argument to the multiplication operation 1639 /// @returns a `ast::BinaryExpression` multiplying `rhs` from `lhs` 1640 template <typename LHS, typename RHS> Mul(LHS && lhs,RHS && rhs)1641 const ast::BinaryExpression* Mul(LHS&& lhs, RHS&& rhs) { 1642 return create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, 1643 Expr(std::forward<LHS>(lhs)), 1644 Expr(std::forward<RHS>(rhs))); 1645 } 1646 1647 /// @param source the source information 1648 /// @param lhs the left hand argument to the multiplication operation 1649 /// @param rhs the right hand argument to the multiplication operation 1650 /// @returns a `ast::BinaryExpression` multiplying `rhs` from `lhs` 1651 template <typename LHS, typename RHS> Mul(const Source & source,LHS && lhs,RHS && rhs)1652 const ast::BinaryExpression* Mul(const Source& source, LHS&& lhs, RHS&& rhs) { 1653 return create<ast::BinaryExpression>(source, ast::BinaryOp::kMultiply, 1654 Expr(std::forward<LHS>(lhs)), 1655 Expr(std::forward<RHS>(rhs))); 1656 } 1657 1658 /// @param lhs the left hand argument to the division operation 1659 /// @param rhs the right hand argument to the division operation 1660 /// @returns a `ast::BinaryExpression` dividing `lhs` by `rhs` 1661 template <typename LHS, typename RHS> Div(LHS && lhs,RHS && rhs)1662 const ast::Expression* Div(LHS&& lhs, RHS&& rhs) { 1663 return create<ast::BinaryExpression>(ast::BinaryOp::kDivide, 1664 Expr(std::forward<LHS>(lhs)), 1665 Expr(std::forward<RHS>(rhs))); 1666 } 1667 1668 /// @param lhs the left hand argument to the bit shift right operation 1669 /// @param rhs the right hand argument to the bit shift right operation 1670 /// @returns a `ast::BinaryExpression` bit shifting right `lhs` by `rhs` 1671 template <typename LHS, typename RHS> Shr(LHS && lhs,RHS && rhs)1672 const ast::BinaryExpression* Shr(LHS&& lhs, RHS&& rhs) { 1673 return create<ast::BinaryExpression>(ast::BinaryOp::kShiftRight, 1674 Expr(std::forward<LHS>(lhs)), 1675 Expr(std::forward<RHS>(rhs))); 1676 } 1677 1678 /// @param lhs the left hand argument to the bit shift left operation 1679 /// @param rhs the right hand argument to the bit shift left operation 1680 /// @returns a `ast::BinaryExpression` bit shifting left `lhs` by `rhs` 1681 template <typename LHS, typename RHS> Shl(LHS && lhs,RHS && rhs)1682 const ast::BinaryExpression* Shl(LHS&& lhs, RHS&& rhs) { 1683 return create<ast::BinaryExpression>(ast::BinaryOp::kShiftLeft, 1684 Expr(std::forward<LHS>(lhs)), 1685 Expr(std::forward<RHS>(rhs))); 1686 } 1687 1688 /// @param lhs the left hand argument to the equal expression 1689 /// @param rhs the right hand argument to the equal expression 1690 /// @returns a `ast::BinaryExpression` comparing `lhs` equal to `rhs` 1691 template <typename LHS, typename RHS> Equal(LHS && lhs,RHS && rhs)1692 const ast::BinaryExpression* Equal(LHS&& lhs, RHS&& rhs) { 1693 return create<ast::BinaryExpression>(ast::BinaryOp::kEqual, 1694 Expr(std::forward<LHS>(lhs)), 1695 Expr(std::forward<RHS>(rhs))); 1696 } 1697 1698 /// @param source the source information 1699 /// @param obj the object for the index accessor expression 1700 /// @param idx the index argument for the index accessor expression 1701 /// @returns a `ast::IndexAccessorExpression` that indexes `arr` with `idx` 1702 template <typename OBJ, typename IDX> IndexAccessor(const Source & source,OBJ && obj,IDX && idx)1703 const ast::IndexAccessorExpression* IndexAccessor(const Source& source, 1704 OBJ&& obj, 1705 IDX&& idx) { 1706 return create<ast::IndexAccessorExpression>( 1707 source, Expr(std::forward<OBJ>(obj)), Expr(std::forward<IDX>(idx))); 1708 } 1709 1710 /// @param obj the object for the index accessor expression 1711 /// @param idx the index argument for the index accessor expression 1712 /// @returns a `ast::IndexAccessorExpression` that indexes `arr` with `idx` 1713 template <typename OBJ, typename IDX> IndexAccessor(OBJ && obj,IDX && idx)1714 const ast::IndexAccessorExpression* IndexAccessor(OBJ&& obj, IDX&& idx) { 1715 return create<ast::IndexAccessorExpression>(Expr(std::forward<OBJ>(obj)), 1716 Expr(std::forward<IDX>(idx))); 1717 } 1718 1719 /// @param source the source information 1720 /// @param obj the object for the member accessor expression 1721 /// @param idx the index argument for the member accessor expression 1722 /// @returns a `ast::MemberAccessorExpression` that indexes `obj` with `idx` 1723 template <typename OBJ, typename IDX> MemberAccessor(const Source & source,OBJ && obj,IDX && idx)1724 const ast::MemberAccessorExpression* MemberAccessor(const Source& source, 1725 OBJ&& obj, 1726 IDX&& idx) { 1727 return create<ast::MemberAccessorExpression>( 1728 source, Expr(std::forward<OBJ>(obj)), Expr(std::forward<IDX>(idx))); 1729 } 1730 1731 /// @param obj the object for the member accessor expression 1732 /// @param idx the index argument for the member accessor expression 1733 /// @returns a `ast::MemberAccessorExpression` that indexes `obj` with `idx` 1734 template <typename OBJ, typename IDX> MemberAccessor(OBJ && obj,IDX && idx)1735 const ast::MemberAccessorExpression* MemberAccessor(OBJ&& obj, IDX&& idx) { 1736 return create<ast::MemberAccessorExpression>(Expr(std::forward<OBJ>(obj)), 1737 Expr(std::forward<IDX>(idx))); 1738 } 1739 1740 /// Creates a ast::StructMemberOffsetDecoration 1741 /// @param val the offset value 1742 /// @returns the offset decoration pointer MemberOffset(uint32_t val)1743 const ast::StructMemberOffsetDecoration* MemberOffset(uint32_t val) { 1744 return create<ast::StructMemberOffsetDecoration>(source_, val); 1745 } 1746 1747 /// Creates a ast::StructMemberSizeDecoration 1748 /// @param source the source information 1749 /// @param val the size value 1750 /// @returns the size decoration pointer MemberSize(const Source & source,uint32_t val)1751 const ast::StructMemberSizeDecoration* MemberSize(const Source& source, 1752 uint32_t val) { 1753 return create<ast::StructMemberSizeDecoration>(source, val); 1754 } 1755 1756 /// Creates a ast::StructMemberSizeDecoration 1757 /// @param val the size value 1758 /// @returns the size decoration pointer MemberSize(uint32_t val)1759 const ast::StructMemberSizeDecoration* MemberSize(uint32_t val) { 1760 return create<ast::StructMemberSizeDecoration>(source_, val); 1761 } 1762 1763 /// Creates a ast::StructMemberAlignDecoration 1764 /// @param source the source information 1765 /// @param val the align value 1766 /// @returns the align decoration pointer MemberAlign(const Source & source,uint32_t val)1767 const ast::StructMemberAlignDecoration* MemberAlign(const Source& source, 1768 uint32_t val) { 1769 return create<ast::StructMemberAlignDecoration>(source, val); 1770 } 1771 1772 /// Creates a ast::StructMemberAlignDecoration 1773 /// @param val the align value 1774 /// @returns the align decoration pointer MemberAlign(uint32_t val)1775 const ast::StructMemberAlignDecoration* MemberAlign(uint32_t val) { 1776 return create<ast::StructMemberAlignDecoration>(source_, val); 1777 } 1778 1779 /// Creates a ast::StructBlockDecoration 1780 /// @returns the struct block decoration pointer StructBlock()1781 const ast::StructBlockDecoration* StructBlock() { 1782 return create<ast::StructBlockDecoration>(); 1783 } 1784 1785 /// Creates the ast::GroupDecoration 1786 /// @param value group decoration index 1787 /// @returns the group decoration pointer Group(uint32_t value)1788 const ast::GroupDecoration* Group(uint32_t value) { 1789 return create<ast::GroupDecoration>(value); 1790 } 1791 1792 /// Creates the ast::BindingDecoration 1793 /// @param value the binding index 1794 /// @returns the binding deocration pointer Binding(uint32_t value)1795 const ast::BindingDecoration* Binding(uint32_t value) { 1796 return create<ast::BindingDecoration>(value); 1797 } 1798 1799 /// Convenience function to create both a ast::GroupDecoration and 1800 /// ast::BindingDecoration 1801 /// @param group the group index 1802 /// @param binding the binding index 1803 /// @returns a decoration list with both the group and binding decorations GroupAndBinding(uint32_t group,uint32_t binding)1804 ast::DecorationList GroupAndBinding(uint32_t group, uint32_t binding) { 1805 return {Group(group), Binding(binding)}; 1806 } 1807 1808 /// Creates an ast::Function and registers it with the ast::Module. 1809 /// @param source the source information 1810 /// @param name the function name 1811 /// @param params the function parameters 1812 /// @param type the function return type 1813 /// @param body the function body 1814 /// @param decorations the optional function decorations 1815 /// @param return_type_decorations the optional function return type 1816 /// decorations 1817 /// @returns the function pointer 1818 template <typename NAME> 1819 const ast::Function* Func(const Source& source, 1820 NAME&& name, 1821 ast::VariableList params, 1822 const ast::Type* type, 1823 ast::StatementList body, 1824 ast::DecorationList decorations = {}, 1825 ast::DecorationList return_type_decorations = {}) { 1826 auto* func = 1827 create<ast::Function>(source, Sym(std::forward<NAME>(name)), params, 1828 type, create<ast::BlockStatement>(body), 1829 decorations, return_type_decorations); 1830 AST().AddFunction(func); 1831 return func; 1832 } 1833 1834 /// Creates an ast::Function and registers it with the ast::Module. 1835 /// @param name the function name 1836 /// @param params the function parameters 1837 /// @param type the function return type 1838 /// @param body the function body 1839 /// @param decorations the optional function decorations 1840 /// @param return_type_decorations the optional function return type 1841 /// decorations 1842 /// @returns the function pointer 1843 template <typename NAME> 1844 const ast::Function* Func(NAME&& name, 1845 ast::VariableList params, 1846 const ast::Type* type, 1847 ast::StatementList body, 1848 ast::DecorationList decorations = {}, 1849 ast::DecorationList return_type_decorations = {}) { 1850 auto* func = create<ast::Function>(Sym(std::forward<NAME>(name)), params, 1851 type, create<ast::BlockStatement>(body), 1852 decorations, return_type_decorations); 1853 AST().AddFunction(func); 1854 return func; 1855 } 1856 1857 /// Creates an ast::BreakStatement 1858 /// @param source the source information 1859 /// @returns the break statement pointer Break(const Source & source)1860 const ast::BreakStatement* Break(const Source& source) { 1861 return create<ast::BreakStatement>(source); 1862 } 1863 1864 /// Creates an ast::BreakStatement 1865 /// @returns the break statement pointer Break()1866 const ast::BreakStatement* Break() { return create<ast::BreakStatement>(); } 1867 1868 /// Creates an ast::ContinueStatement 1869 /// @param source the source information 1870 /// @returns the continue statement pointer Continue(const Source & source)1871 const ast::ContinueStatement* Continue(const Source& source) { 1872 return create<ast::ContinueStatement>(source); 1873 } 1874 1875 /// Creates an ast::ContinueStatement 1876 /// @returns the continue statement pointer Continue()1877 const ast::ContinueStatement* Continue() { 1878 return create<ast::ContinueStatement>(); 1879 } 1880 1881 /// Creates an ast::ReturnStatement with no return value 1882 /// @param source the source information 1883 /// @returns the return statement pointer Return(const Source & source)1884 const ast::ReturnStatement* Return(const Source& source) { 1885 return create<ast::ReturnStatement>(source); 1886 } 1887 1888 /// Creates an ast::ReturnStatement with no return value 1889 /// @returns the return statement pointer Return()1890 const ast::ReturnStatement* Return() { 1891 return create<ast::ReturnStatement>(); 1892 } 1893 1894 /// Creates an ast::ReturnStatement with the given return value 1895 /// @param source the source information 1896 /// @param val the return value 1897 /// @returns the return statement pointer 1898 template <typename EXPR> Return(const Source & source,EXPR && val)1899 const ast::ReturnStatement* Return(const Source& source, EXPR&& val) { 1900 return create<ast::ReturnStatement>(source, Expr(std::forward<EXPR>(val))); 1901 } 1902 1903 /// Creates an ast::ReturnStatement with the given return value 1904 /// @param val the return value 1905 /// @returns the return statement pointer 1906 template <typename EXPR, typename = DisableIfSource<EXPR>> Return(EXPR && val)1907 const ast::ReturnStatement* Return(EXPR&& val) { 1908 return create<ast::ReturnStatement>(Expr(std::forward<EXPR>(val))); 1909 } 1910 1911 /// Creates an ast::DiscardStatement 1912 /// @param source the source information 1913 /// @returns the discard statement pointer Discard(const Source & source)1914 const ast::DiscardStatement* Discard(const Source& source) { 1915 return create<ast::DiscardStatement>(source); 1916 } 1917 1918 /// Creates an ast::DiscardStatement 1919 /// @returns the discard statement pointer Discard()1920 const ast::DiscardStatement* Discard() { 1921 return create<ast::DiscardStatement>(); 1922 } 1923 1924 /// Creates a ast::Alias registering it with the AST().TypeDecls(). 1925 /// @param source the source information 1926 /// @param name the alias name 1927 /// @param type the alias target type 1928 /// @returns the alias type 1929 template <typename NAME> Alias(const Source & source,NAME && name,const ast::Type * type)1930 const ast::Alias* Alias(const Source& source, 1931 NAME&& name, 1932 const ast::Type* type) { 1933 auto* out = ty.alias(source, std::forward<NAME>(name), type); 1934 AST().AddTypeDecl(out); 1935 return out; 1936 } 1937 1938 /// Creates a ast::Alias registering it with the AST().TypeDecls(). 1939 /// @param name the alias name 1940 /// @param type the alias target type 1941 /// @returns the alias type 1942 template <typename NAME> Alias(NAME && name,const ast::Type * type)1943 const ast::Alias* Alias(NAME&& name, const ast::Type* type) { 1944 auto* out = ty.alias(std::forward<NAME>(name), type); 1945 AST().AddTypeDecl(out); 1946 return out; 1947 } 1948 1949 /// Creates a ast::Struct registering it with the AST().TypeDecls(). 1950 /// @param source the source information 1951 /// @param name the struct name 1952 /// @param members the struct members 1953 /// @param decorations the optional struct decorations 1954 /// @returns the struct type 1955 template <typename NAME> 1956 const ast::Struct* Structure(const Source& source, 1957 NAME&& name, 1958 ast::StructMemberList members, 1959 ast::DecorationList decorations = {}) { 1960 auto sym = Sym(std::forward<NAME>(name)); 1961 auto* type = create<ast::Struct>(source, sym, std::move(members), 1962 std::move(decorations)); 1963 AST().AddTypeDecl(type); 1964 return type; 1965 } 1966 1967 /// Creates a ast::Struct registering it with the AST().TypeDecls(). 1968 /// @param name the struct name 1969 /// @param members the struct members 1970 /// @param decorations the optional struct decorations 1971 /// @returns the struct type 1972 template <typename NAME> 1973 const ast::Struct* Structure(NAME&& name, 1974 ast::StructMemberList members, 1975 ast::DecorationList decorations = {}) { 1976 auto sym = Sym(std::forward<NAME>(name)); 1977 auto* type = 1978 create<ast::Struct>(sym, std::move(members), std::move(decorations)); 1979 AST().AddTypeDecl(type); 1980 return type; 1981 } 1982 1983 /// Creates a ast::StructMember 1984 /// @param source the source information 1985 /// @param name the struct member name 1986 /// @param type the struct member type 1987 /// @param decorations the optional struct member decorations 1988 /// @returns the struct member pointer 1989 template <typename NAME> 1990 const ast::StructMember* Member(const Source& source, 1991 NAME&& name, 1992 const ast::Type* type, 1993 ast::DecorationList decorations = {}) { 1994 return create<ast::StructMember>(source, Sym(std::forward<NAME>(name)), 1995 type, std::move(decorations)); 1996 } 1997 1998 /// Creates a ast::StructMember 1999 /// @param name the struct member name 2000 /// @param type the struct member type 2001 /// @param decorations the optional struct member decorations 2002 /// @returns the struct member pointer 2003 template <typename NAME> 2004 const ast::StructMember* Member(NAME&& name, 2005 const ast::Type* type, 2006 ast::DecorationList decorations = {}) { 2007 return create<ast::StructMember>(source_, Sym(std::forward<NAME>(name)), 2008 type, std::move(decorations)); 2009 } 2010 2011 /// Creates a ast::StructMember with the given byte offset 2012 /// @param offset the offset to use in the StructMemberOffsetDecoration 2013 /// @param name the struct member name 2014 /// @param type the struct member type 2015 /// @returns the struct member pointer 2016 template <typename NAME> Member(uint32_t offset,NAME && name,const ast::Type * type)2017 const ast::StructMember* Member(uint32_t offset, 2018 NAME&& name, 2019 const ast::Type* type) { 2020 return create<ast::StructMember>( 2021 source_, Sym(std::forward<NAME>(name)), type, 2022 ast::DecorationList{ 2023 create<ast::StructMemberOffsetDecoration>(offset), 2024 }); 2025 } 2026 2027 /// Creates a ast::BlockStatement with input statements 2028 /// @param source the source information for the block 2029 /// @param statements statements of block 2030 /// @returns the block statement pointer 2031 template <typename... Statements> Block(const Source & source,Statements &&...statements)2032 const ast::BlockStatement* Block(const Source& source, 2033 Statements&&... statements) { 2034 return create<ast::BlockStatement>( 2035 source, ast::StatementList{std::forward<Statements>(statements)...}); 2036 } 2037 2038 /// Creates a ast::BlockStatement with input statements 2039 /// @param statements statements of block 2040 /// @returns the block statement pointer 2041 template <typename... STATEMENTS, typename = DisableIfSource<STATEMENTS...>> Block(STATEMENTS &&...statements)2042 const ast::BlockStatement* Block(STATEMENTS&&... statements) { 2043 return create<ast::BlockStatement>( 2044 ast::StatementList{std::forward<STATEMENTS>(statements)...}); 2045 } 2046 2047 /// Creates a ast::ElseStatement with input condition and body 2048 /// @param condition the else condition expression 2049 /// @param body the else body 2050 /// @returns the else statement pointer 2051 template <typename CONDITION> Else(CONDITION && condition,const ast::BlockStatement * body)2052 const ast::ElseStatement* Else(CONDITION&& condition, 2053 const ast::BlockStatement* body) { 2054 return create<ast::ElseStatement>(Expr(std::forward<CONDITION>(condition)), 2055 body); 2056 } 2057 2058 /// Creates a ast::ElseStatement with no condition and body 2059 /// @param body the else body 2060 /// @returns the else statement pointer Else(const ast::BlockStatement * body)2061 const ast::ElseStatement* Else(const ast::BlockStatement* body) { 2062 return create<ast::ElseStatement>(nullptr, body); 2063 } 2064 2065 /// Creates a ast::IfStatement with input condition, body, and optional 2066 /// variadic else statements 2067 /// @param condition the if statement condition expression 2068 /// @param body the if statement body 2069 /// @param elseStatements optional variadic else statements 2070 /// @returns the if statement pointer 2071 template <typename CONDITION, typename... ELSE_STATEMENTS> If(CONDITION && condition,const ast::BlockStatement * body,ELSE_STATEMENTS &&...elseStatements)2072 const ast::IfStatement* If(CONDITION&& condition, 2073 const ast::BlockStatement* body, 2074 ELSE_STATEMENTS&&... elseStatements) { 2075 return create<ast::IfStatement>( 2076 Expr(std::forward<CONDITION>(condition)), body, 2077 ast::ElseStatementList{ 2078 std::forward<ELSE_STATEMENTS>(elseStatements)...}); 2079 } 2080 2081 /// Creates a ast::AssignmentStatement with input lhs and rhs expressions 2082 /// @param source the source information 2083 /// @param lhs the left hand side expression initializer 2084 /// @param rhs the right hand side expression initializer 2085 /// @returns the assignment statement pointer 2086 template <typename LhsExpressionInit, typename RhsExpressionInit> Assign(const Source & source,LhsExpressionInit && lhs,RhsExpressionInit && rhs)2087 const ast::AssignmentStatement* Assign(const Source& source, 2088 LhsExpressionInit&& lhs, 2089 RhsExpressionInit&& rhs) { 2090 return create<ast::AssignmentStatement>( 2091 source, Expr(std::forward<LhsExpressionInit>(lhs)), 2092 Expr(std::forward<RhsExpressionInit>(rhs))); 2093 } 2094 2095 /// Creates a ast::AssignmentStatement with input lhs and rhs expressions 2096 /// @param lhs the left hand side expression initializer 2097 /// @param rhs the right hand side expression initializer 2098 /// @returns the assignment statement pointer 2099 template <typename LhsExpressionInit, typename RhsExpressionInit> Assign(LhsExpressionInit && lhs,RhsExpressionInit && rhs)2100 const ast::AssignmentStatement* Assign(LhsExpressionInit&& lhs, 2101 RhsExpressionInit&& rhs) { 2102 return create<ast::AssignmentStatement>( 2103 Expr(std::forward<LhsExpressionInit>(lhs)), 2104 Expr(std::forward<RhsExpressionInit>(rhs))); 2105 } 2106 2107 /// Creates a ast::LoopStatement with input body and optional continuing 2108 /// @param source the source information 2109 /// @param body the loop body 2110 /// @param continuing the optional continuing block 2111 /// @returns the loop statement pointer 2112 const ast::LoopStatement* Loop( 2113 const Source& source, 2114 const ast::BlockStatement* body, 2115 const ast::BlockStatement* continuing = nullptr) { 2116 return create<ast::LoopStatement>(source, body, continuing); 2117 } 2118 2119 /// Creates a ast::LoopStatement with input body and optional continuing 2120 /// @param body the loop body 2121 /// @param continuing the optional continuing block 2122 /// @returns the loop statement pointer 2123 const ast::LoopStatement* Loop( 2124 const ast::BlockStatement* body, 2125 const ast::BlockStatement* continuing = nullptr) { 2126 return create<ast::LoopStatement>(body, continuing); 2127 } 2128 2129 /// Creates a ast::ForLoopStatement with input body and optional initializer, 2130 /// condition and continuing. 2131 /// @param source the source information 2132 /// @param init the optional loop initializer 2133 /// @param cond the optional loop condition 2134 /// @param cont the optional loop continuing 2135 /// @param body the loop body 2136 /// @returns the for loop statement pointer 2137 template <typename COND> For(const Source & source,const ast::Statement * init,COND && cond,const ast::Statement * cont,const ast::BlockStatement * body)2138 const ast::ForLoopStatement* For(const Source& source, 2139 const ast::Statement* init, 2140 COND&& cond, 2141 const ast::Statement* cont, 2142 const ast::BlockStatement* body) { 2143 return create<ast::ForLoopStatement>( 2144 source, init, Expr(std::forward<COND>(cond)), cont, body); 2145 } 2146 2147 /// Creates a ast::ForLoopStatement with input body and optional initializer, 2148 /// condition and continuing. 2149 /// @param init the optional loop initializer 2150 /// @param cond the optional loop condition 2151 /// @param cont the optional loop continuing 2152 /// @param body the loop body 2153 /// @returns the for loop statement pointer 2154 template <typename COND> For(const ast::Statement * init,COND && cond,const ast::Statement * cont,const ast::BlockStatement * body)2155 const ast::ForLoopStatement* For(const ast::Statement* init, 2156 COND&& cond, 2157 const ast::Statement* cont, 2158 const ast::BlockStatement* body) { 2159 return create<ast::ForLoopStatement>(init, Expr(std::forward<COND>(cond)), 2160 cont, body); 2161 } 2162 2163 /// Creates a ast::VariableDeclStatement for the input variable 2164 /// @param source the source information 2165 /// @param var the variable to wrap in a decl statement 2166 /// @returns the variable decl statement pointer Decl(const Source & source,const ast::Variable * var)2167 const ast::VariableDeclStatement* Decl(const Source& source, 2168 const ast::Variable* var) { 2169 return create<ast::VariableDeclStatement>(source, var); 2170 } 2171 2172 /// Creates a ast::VariableDeclStatement for the input variable 2173 /// @param var the variable to wrap in a decl statement 2174 /// @returns the variable decl statement pointer Decl(const ast::Variable * var)2175 const ast::VariableDeclStatement* Decl(const ast::Variable* var) { 2176 return create<ast::VariableDeclStatement>(var); 2177 } 2178 2179 /// Creates a ast::SwitchStatement with input expression and cases 2180 /// @param source the source information 2181 /// @param condition the condition expression initializer 2182 /// @param cases case statements 2183 /// @returns the switch statement pointer 2184 template <typename ExpressionInit, typename... Cases> Switch(const Source & source,ExpressionInit && condition,Cases &&...cases)2185 const ast::SwitchStatement* Switch(const Source& source, 2186 ExpressionInit&& condition, 2187 Cases&&... cases) { 2188 return create<ast::SwitchStatement>( 2189 source, Expr(std::forward<ExpressionInit>(condition)), 2190 ast::CaseStatementList{std::forward<Cases>(cases)...}); 2191 } 2192 2193 /// Creates a ast::SwitchStatement with input expression and cases 2194 /// @param condition the condition expression initializer 2195 /// @param cases case statements 2196 /// @returns the switch statement pointer 2197 template <typename ExpressionInit, 2198 typename... Cases, 2199 typename = DisableIfSource<ExpressionInit>> Switch(ExpressionInit && condition,Cases &&...cases)2200 const ast::SwitchStatement* Switch(ExpressionInit&& condition, 2201 Cases&&... cases) { 2202 return create<ast::SwitchStatement>( 2203 Expr(std::forward<ExpressionInit>(condition)), 2204 ast::CaseStatementList{std::forward<Cases>(cases)...}); 2205 } 2206 2207 /// Creates a ast::CaseStatement with input list of selectors, and body 2208 /// @param source the source information 2209 /// @param selectors list of selectors 2210 /// @param body the case body 2211 /// @returns the case statement pointer 2212 const ast::CaseStatement* Case(const Source& source, 2213 ast::CaseSelectorList selectors, 2214 const ast::BlockStatement* body = nullptr) { 2215 return create<ast::CaseStatement>(source, std::move(selectors), 2216 body ? body : Block()); 2217 } 2218 2219 /// Creates a ast::CaseStatement with input list of selectors, and body 2220 /// @param selectors list of selectors 2221 /// @param body the case body 2222 /// @returns the case statement pointer 2223 const ast::CaseStatement* Case(ast::CaseSelectorList selectors, 2224 const ast::BlockStatement* body = nullptr) { 2225 return create<ast::CaseStatement>(std::move(selectors), 2226 body ? body : Block()); 2227 } 2228 2229 /// Convenient overload that takes a single selector 2230 /// @param selector a single case selector 2231 /// @param body the case body 2232 /// @returns the case statement pointer 2233 const ast::CaseStatement* Case(const ast::IntLiteralExpression* selector, 2234 const ast::BlockStatement* body = nullptr) { 2235 return Case(ast::CaseSelectorList{selector}, body); 2236 } 2237 2238 /// Convenience function that creates a 'default' ast::CaseStatement 2239 /// @param source the source information 2240 /// @param body the case body 2241 /// @returns the case statement pointer 2242 const ast::CaseStatement* DefaultCase( 2243 const Source& source, 2244 const ast::BlockStatement* body = nullptr) { 2245 return Case(source, ast::CaseSelectorList{}, body); 2246 } 2247 2248 /// Convenience function that creates a 'default' ast::CaseStatement 2249 /// @param body the case body 2250 /// @returns the case statement pointer 2251 const ast::CaseStatement* DefaultCase( 2252 const ast::BlockStatement* body = nullptr) { 2253 return Case(ast::CaseSelectorList{}, body); 2254 } 2255 2256 /// Creates an ast::FallthroughStatement 2257 /// @param source the source information 2258 /// @returns the fallthrough statement pointer Fallthrough(const Source & source)2259 const ast::FallthroughStatement* Fallthrough(const Source& source) { 2260 return create<ast::FallthroughStatement>(source); 2261 } 2262 2263 /// Creates an ast::FallthroughStatement 2264 /// @returns the fallthrough statement pointer Fallthrough()2265 const ast::FallthroughStatement* Fallthrough() { 2266 return create<ast::FallthroughStatement>(); 2267 } 2268 2269 /// Creates an ast::BuiltinDecoration 2270 /// @param source the source information 2271 /// @param builtin the builtin value 2272 /// @returns the builtin decoration pointer Builtin(const Source & source,ast::Builtin builtin)2273 const ast::BuiltinDecoration* Builtin(const Source& source, 2274 ast::Builtin builtin) { 2275 return create<ast::BuiltinDecoration>(source, builtin); 2276 } 2277 2278 /// Creates an ast::BuiltinDecoration 2279 /// @param builtin the builtin value 2280 /// @returns the builtin decoration pointer Builtin(ast::Builtin builtin)2281 const ast::BuiltinDecoration* Builtin(ast::Builtin builtin) { 2282 return create<ast::BuiltinDecoration>(source_, builtin); 2283 } 2284 2285 /// Creates an ast::InterpolateDecoration 2286 /// @param source the source information 2287 /// @param type the interpolation type 2288 /// @param sampling the interpolation sampling 2289 /// @returns the interpolate decoration pointer Interpolate(const Source & source,ast::InterpolationType type,ast::InterpolationSampling sampling)2290 const ast::InterpolateDecoration* Interpolate( 2291 const Source& source, 2292 ast::InterpolationType type, 2293 ast::InterpolationSampling sampling) { 2294 return create<ast::InterpolateDecoration>(source, type, sampling); 2295 } 2296 2297 /// Creates an ast::InterpolateDecoration 2298 /// @param type the interpolation type 2299 /// @param sampling the interpolation sampling 2300 /// @returns the interpolate decoration pointer Interpolate(ast::InterpolationType type,ast::InterpolationSampling sampling)2301 const ast::InterpolateDecoration* Interpolate( 2302 ast::InterpolationType type, 2303 ast::InterpolationSampling sampling) { 2304 return create<ast::InterpolateDecoration>(source_, type, sampling); 2305 } 2306 2307 /// Creates an ast::InvariantDecoration 2308 /// @param source the source information 2309 /// @returns the invariant decoration pointer Invariant(const Source & source)2310 const ast::InvariantDecoration* Invariant(const Source& source) { 2311 return create<ast::InvariantDecoration>(source); 2312 } 2313 2314 /// Creates an ast::InvariantDecoration 2315 /// @returns the invariant decoration pointer Invariant()2316 const ast::InvariantDecoration* Invariant() { 2317 return create<ast::InvariantDecoration>(source_); 2318 } 2319 2320 /// Creates an ast::LocationDecoration 2321 /// @param source the source information 2322 /// @param location the location value 2323 /// @returns the location decoration pointer Location(const Source & source,uint32_t location)2324 const ast::LocationDecoration* Location(const Source& source, 2325 uint32_t location) { 2326 return create<ast::LocationDecoration>(source, location); 2327 } 2328 2329 /// Creates an ast::LocationDecoration 2330 /// @param location the location value 2331 /// @returns the location decoration pointer Location(uint32_t location)2332 const ast::LocationDecoration* Location(uint32_t location) { 2333 return create<ast::LocationDecoration>(source_, location); 2334 } 2335 2336 /// Creates an ast::OverrideDecoration with a specific constant ID 2337 /// @param source the source information 2338 /// @param id the id value 2339 /// @returns the override decoration pointer Override(const Source & source,uint32_t id)2340 const ast::OverrideDecoration* Override(const Source& source, uint32_t id) { 2341 return create<ast::OverrideDecoration>(source, id); 2342 } 2343 2344 /// Creates an ast::OverrideDecoration with a specific constant ID 2345 /// @param id the optional id value 2346 /// @returns the override decoration pointer Override(uint32_t id)2347 const ast::OverrideDecoration* Override(uint32_t id) { 2348 return Override(source_, id); 2349 } 2350 2351 /// Creates an ast::OverrideDecoration without a constant ID 2352 /// @param source the source information 2353 /// @returns the override decoration pointer Override(const Source & source)2354 const ast::OverrideDecoration* Override(const Source& source) { 2355 return create<ast::OverrideDecoration>(source); 2356 } 2357 2358 /// Creates an ast::OverrideDecoration without a constant ID 2359 /// @returns the override decoration pointer Override()2360 const ast::OverrideDecoration* Override() { return Override(source_); } 2361 2362 /// Creates an ast::StageDecoration 2363 /// @param source the source information 2364 /// @param stage the pipeline stage 2365 /// @returns the stage decoration pointer Stage(const Source & source,ast::PipelineStage stage)2366 const ast::StageDecoration* Stage(const Source& source, 2367 ast::PipelineStage stage) { 2368 return create<ast::StageDecoration>(source, stage); 2369 } 2370 2371 /// Creates an ast::StageDecoration 2372 /// @param stage the pipeline stage 2373 /// @returns the stage decoration pointer Stage(ast::PipelineStage stage)2374 const ast::StageDecoration* Stage(ast::PipelineStage stage) { 2375 return create<ast::StageDecoration>(source_, stage); 2376 } 2377 2378 /// Creates an ast::WorkgroupDecoration 2379 /// @param x the x dimension expression 2380 /// @returns the workgroup decoration pointer 2381 template <typename EXPR_X> WorkgroupSize(EXPR_X && x)2382 const ast::WorkgroupDecoration* WorkgroupSize(EXPR_X&& x) { 2383 return WorkgroupSize(std::forward<EXPR_X>(x), nullptr, nullptr); 2384 } 2385 2386 /// Creates an ast::WorkgroupDecoration 2387 /// @param x the x dimension expression 2388 /// @param y the y dimension expression 2389 /// @returns the workgroup decoration pointer 2390 template <typename EXPR_X, typename EXPR_Y> WorkgroupSize(EXPR_X && x,EXPR_Y && y)2391 const ast::WorkgroupDecoration* WorkgroupSize(EXPR_X&& x, EXPR_Y&& y) { 2392 return WorkgroupSize(std::forward<EXPR_X>(x), std::forward<EXPR_Y>(y), 2393 nullptr); 2394 } 2395 2396 /// Creates an ast::WorkgroupDecoration 2397 /// @param source the source information 2398 /// @param x the x dimension expression 2399 /// @param y the y dimension expression 2400 /// @param z the z dimension expression 2401 /// @returns the workgroup decoration pointer 2402 template <typename EXPR_X, typename EXPR_Y, typename EXPR_Z> WorkgroupSize(const Source & source,EXPR_X && x,EXPR_Y && y,EXPR_Z && z)2403 const ast::WorkgroupDecoration* WorkgroupSize(const Source& source, 2404 EXPR_X&& x, 2405 EXPR_Y&& y, 2406 EXPR_Z&& z) { 2407 return create<ast::WorkgroupDecoration>( 2408 source, Expr(std::forward<EXPR_X>(x)), Expr(std::forward<EXPR_Y>(y)), 2409 Expr(std::forward<EXPR_Z>(z))); 2410 } 2411 2412 /// Creates an ast::WorkgroupDecoration 2413 /// @param x the x dimension expression 2414 /// @param y the y dimension expression 2415 /// @param z the z dimension expression 2416 /// @returns the workgroup decoration pointer 2417 template <typename EXPR_X, typename EXPR_Y, typename EXPR_Z> WorkgroupSize(EXPR_X && x,EXPR_Y && y,EXPR_Z && z)2418 const ast::WorkgroupDecoration* WorkgroupSize(EXPR_X&& x, 2419 EXPR_Y&& y, 2420 EXPR_Z&& z) { 2421 return create<ast::WorkgroupDecoration>( 2422 source_, Expr(std::forward<EXPR_X>(x)), Expr(std::forward<EXPR_Y>(y)), 2423 Expr(std::forward<EXPR_Z>(z))); 2424 } 2425 2426 /// Creates an ast::DisableValidationDecoration 2427 /// @param validation the validation to disable 2428 /// @returns the disable validation decoration pointer Disable(ast::DisabledValidation validation)2429 const ast::DisableValidationDecoration* Disable( 2430 ast::DisabledValidation validation) { 2431 return ASTNodes().Create<ast::DisableValidationDecoration>(ID(), 2432 validation); 2433 } 2434 2435 /// Sets the current builder source to `src` 2436 /// @param src the Source used for future create() calls SetSource(const Source & src)2437 void SetSource(const Source& src) { 2438 AssertNotMoved(); 2439 source_ = src; 2440 } 2441 2442 /// Sets the current builder source to `loc` 2443 /// @param loc the Source used for future create() calls SetSource(const Source::Location & loc)2444 void SetSource(const Source::Location& loc) { 2445 AssertNotMoved(); 2446 source_ = Source(loc); 2447 } 2448 2449 /// Marks that the given transform has been applied to this program. 2450 /// @param transform the transform that has been applied SetTransformApplied(const CastableBase * transform)2451 void SetTransformApplied(const CastableBase* transform) { 2452 transforms_applied_.emplace(&transform->TypeInfo()); 2453 } 2454 2455 /// Marks that the given transform `T` has been applied to this program. 2456 template <typename T> SetTransformApplied()2457 void SetTransformApplied() { 2458 transforms_applied_.emplace(&TypeInfo::Of<T>()); 2459 } 2460 2461 /// Marks that the transforms with the given TypeInfos have been applied to 2462 /// this program. 2463 /// @param transforms the set of transform TypeInfos that has been applied SetTransformApplied(const std::unordered_set<const TypeInfo * > & transforms)2464 void SetTransformApplied( 2465 const std::unordered_set<const TypeInfo*>& transforms) { 2466 for (auto* transform : transforms) { 2467 transforms_applied_.emplace(transform); 2468 } 2469 } 2470 2471 /// @returns true if the transform of type `T` was applied. 2472 template <typename T> HasTransformApplied()2473 bool HasTransformApplied() { 2474 return transforms_applied_.count(&TypeInfo::Of<T>()); 2475 } 2476 2477 /// @return the TypeInfo pointers of all transforms that have been applied to 2478 /// this program. TransformsApplied()2479 std::unordered_set<const TypeInfo*> TransformsApplied() const { 2480 return transforms_applied_; 2481 } 2482 2483 /// Helper for returning the resolved semantic type of the expression `expr`. 2484 /// @note As the Resolver is run when the Program is built, this will only be 2485 /// useful for the Resolver itself and tests that use their own Resolver. 2486 /// @param expr the AST expression 2487 /// @return the resolved semantic type for the expression, or nullptr if the 2488 /// expression has no resolved type. 2489 const sem::Type* TypeOf(const ast::Expression* expr) const; 2490 2491 /// Helper for returning the resolved semantic type of the variable `var`. 2492 /// @note As the Resolver is run when the Program is built, this will only be 2493 /// useful for the Resolver itself and tests that use their own Resolver. 2494 /// @param var the AST variable 2495 /// @return the resolved semantic type for the variable, or nullptr if the 2496 /// variable has no resolved type. 2497 const sem::Type* TypeOf(const ast::Variable* var) const; 2498 2499 /// Helper for returning the resolved semantic type of the AST type `type`. 2500 /// @note As the Resolver is run when the Program is built, this will only be 2501 /// useful for the Resolver itself and tests that use their own Resolver. 2502 /// @param type the AST type 2503 /// @return the resolved semantic type for the type, or nullptr if the type 2504 /// has no resolved type. 2505 const sem::Type* TypeOf(const ast::Type* type) const; 2506 2507 /// Helper for returning the resolved semantic type of the AST type 2508 /// declaration `type_decl`. 2509 /// @note As the Resolver is run when the Program is built, this will only be 2510 /// useful for the Resolver itself and tests that use their own Resolver. 2511 /// @param type_decl the AST type declaration 2512 /// @return the resolved semantic type for the type declaration, or nullptr if 2513 /// the type declaration has no resolved type. 2514 const sem::Type* TypeOf(const ast::TypeDecl* type_decl) const; 2515 2516 /// Wraps the ast::Expression in a statement. This is used by tests that 2517 /// construct a partial AST and require the Resolver to reach these 2518 /// nodes. 2519 /// @param expr the ast::Expression to be wrapped by an ast::Statement 2520 /// @return the ast::Statement that wraps the ast::Expression 2521 const ast::Statement* WrapInStatement(const ast::Expression* expr); 2522 /// Wraps the ast::Variable in a ast::VariableDeclStatement. This is used by 2523 /// tests that construct a partial AST and require the Resolver to reach 2524 /// these nodes. 2525 /// @param v the ast::Variable to be wrapped by an ast::VariableDeclStatement 2526 /// @return the ast::VariableDeclStatement that wraps the ast::Variable 2527 const ast::VariableDeclStatement* WrapInStatement(const ast::Variable* v); 2528 /// Returns the statement argument. Used as a passthrough-overload by 2529 /// WrapInFunction(). 2530 /// @param stmt the ast::Statement 2531 /// @return `stmt` 2532 const ast::Statement* WrapInStatement(const ast::Statement* stmt); 2533 /// Wraps the list of arguments in a simple function so that each is reachable 2534 /// by the Resolver. 2535 /// @param args a mix of ast::Expression, ast::Statement, ast::Variables. 2536 /// @returns the function 2537 template <typename... ARGS> WrapInFunction(ARGS &&...args)2538 const ast::Function* WrapInFunction(ARGS&&... args) { 2539 ast::StatementList stmts{WrapInStatement(std::forward<ARGS>(args))...}; 2540 return WrapInFunction(std::move(stmts)); 2541 } 2542 /// @param stmts a list of ast::Statement that will be wrapped by a function, 2543 /// so that each statement is reachable by the Resolver. 2544 /// @returns the function 2545 const ast::Function* WrapInFunction(ast::StatementList stmts); 2546 2547 /// The builder types 2548 TypesBuilder const ty{this}; 2549 2550 protected: 2551 /// Asserts that the builder has not been moved. 2552 void AssertNotMoved() const; 2553 2554 private: 2555 ProgramID id_; 2556 sem::Manager types_; 2557 ASTNodeAllocator ast_nodes_; 2558 SemNodeAllocator sem_nodes_; 2559 ast::Module* ast_; 2560 sem::Info sem_; 2561 SymbolTable symbols_{id_}; 2562 diag::List diagnostics_; 2563 std::unordered_set<const TypeInfo*> transforms_applied_; 2564 2565 /// The source to use when creating AST nodes without providing a Source as 2566 /// the first argument. 2567 Source source_; 2568 2569 /// Set by SetResolveOnBuild(). If set, the Resolver will be run on the 2570 /// program when built. 2571 bool resolve_on_build_ = true; 2572 2573 /// Set by MarkAsMoved(). Once set, no methods may be called on this builder. 2574 bool moved_ = false; 2575 }; 2576 2577 //! @cond Doxygen_Suppress 2578 // Various template specializations for ProgramBuilder::TypesBuilder::CToAST. 2579 template <> 2580 struct ProgramBuilder::TypesBuilder::CToAST<ProgramBuilder::i32> { 2581 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { 2582 return t->i32(); 2583 } 2584 }; 2585 template <> 2586 struct ProgramBuilder::TypesBuilder::CToAST<ProgramBuilder::u32> { 2587 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { 2588 return t->u32(); 2589 } 2590 }; 2591 template <> 2592 struct ProgramBuilder::TypesBuilder::CToAST<ProgramBuilder::f32> { 2593 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { 2594 return t->f32(); 2595 } 2596 }; 2597 template <> 2598 struct ProgramBuilder::TypesBuilder::CToAST<bool> { 2599 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { 2600 return t->bool_(); 2601 } 2602 }; 2603 template <> 2604 struct ProgramBuilder::TypesBuilder::CToAST<void> { 2605 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { 2606 return t->void_(); 2607 } 2608 }; 2609 //! @endcond 2610 2611 /// @param builder the ProgramBuilder 2612 /// @returns the ProgramID of the ProgramBuilder 2613 inline ProgramID ProgramIDOf(const ProgramBuilder* builder) { 2614 return builder->ID(); 2615 } 2616 2617 } // namespace tint 2618 2619 #endif // SRC_PROGRAM_BUILDER_H_ 2620