blob: 088efc95619ebdd8403998ac338d68190771841f [file] [log] [blame]
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001// Copyright 2021 The Tint Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef SRC_TINT_PROGRAM_BUILDER_H_
16#define SRC_TINT_PROGRAM_BUILDER_H_
17
18#include <string>
19#include <unordered_set>
20#include <utility>
21
22#include "src/tint/ast/alias.h"
23#include "src/tint/ast/array.h"
24#include "src/tint/ast/assignment_statement.h"
25#include "src/tint/ast/atomic.h"
26#include "src/tint/ast/binary_expression.h"
27#include "src/tint/ast/binding_attribute.h"
28#include "src/tint/ast/bitcast_expression.h"
29#include "src/tint/ast/bool.h"
30#include "src/tint/ast/bool_literal_expression.h"
31#include "src/tint/ast/break_statement.h"
32#include "src/tint/ast/call_expression.h"
33#include "src/tint/ast/call_statement.h"
34#include "src/tint/ast/case_statement.h"
James Pricec022ff52022-03-31 22:30:10 +000035#include "src/tint/ast/compound_assignment_statement.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000036#include "src/tint/ast/continue_statement.h"
37#include "src/tint/ast/depth_multisampled_texture.h"
38#include "src/tint/ast/depth_texture.h"
39#include "src/tint/ast/disable_validation_attribute.h"
40#include "src/tint/ast/discard_statement.h"
Zhaoming Jiang7098d3d2022-04-27 02:27:52 +000041#include "src/tint/ast/enable.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000042#include "src/tint/ast/external_texture.h"
43#include "src/tint/ast/f32.h"
44#include "src/tint/ast/fallthrough_statement.h"
45#include "src/tint/ast/float_literal_expression.h"
46#include "src/tint/ast/for_loop_statement.h"
47#include "src/tint/ast/i32.h"
48#include "src/tint/ast/id_attribute.h"
49#include "src/tint/ast/if_statement.h"
James Priceebe97412022-04-07 13:42:45 +000050#include "src/tint/ast/increment_decrement_statement.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000051#include "src/tint/ast/index_accessor_expression.h"
52#include "src/tint/ast/interpolate_attribute.h"
53#include "src/tint/ast/invariant_attribute.h"
54#include "src/tint/ast/loop_statement.h"
55#include "src/tint/ast/matrix.h"
56#include "src/tint/ast/member_accessor_expression.h"
57#include "src/tint/ast/module.h"
58#include "src/tint/ast/multisampled_texture.h"
59#include "src/tint/ast/phony_expression.h"
60#include "src/tint/ast/pointer.h"
61#include "src/tint/ast/return_statement.h"
62#include "src/tint/ast/sampled_texture.h"
63#include "src/tint/ast/sampler.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000064#include "src/tint/ast/stage_attribute.h"
65#include "src/tint/ast/storage_texture.h"
66#include "src/tint/ast/stride_attribute.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000067#include "src/tint/ast/struct_member_align_attribute.h"
68#include "src/tint/ast/struct_member_offset_attribute.h"
69#include "src/tint/ast/struct_member_size_attribute.h"
70#include "src/tint/ast/switch_statement.h"
71#include "src/tint/ast/type_name.h"
72#include "src/tint/ast/u32.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000073#include "src/tint/ast/unary_op_expression.h"
74#include "src/tint/ast/variable_decl_statement.h"
75#include "src/tint/ast/vector.h"
76#include "src/tint/ast/void.h"
77#include "src/tint/ast/workgroup_attribute.h"
Ben Clayton0ce9ab02022-05-05 20:23:40 +000078#include "src/tint/number.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000079#include "src/tint/program.h"
80#include "src/tint/program_id.h"
81#include "src/tint/sem/array.h"
Ben Clayton01004b72022-04-28 18:49:04 +000082#include "src/tint/sem/bool.h"
83#include "src/tint/sem/depth_texture.h"
84#include "src/tint/sem/external_texture.h"
85#include "src/tint/sem/f32.h"
86#include "src/tint/sem/i32.h"
87#include "src/tint/sem/matrix.h"
88#include "src/tint/sem/multisampled_texture.h"
89#include "src/tint/sem/pointer.h"
90#include "src/tint/sem/sampled_texture.h"
91#include "src/tint/sem/storage_texture.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000092#include "src/tint/sem/struct.h"
Ben Clayton01004b72022-04-28 18:49:04 +000093#include "src/tint/sem/u32.h"
94#include "src/tint/sem/vector.h"
95#include "src/tint/sem/void.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000096
97#ifdef INCLUDE_TINT_TINT_H_
98#error "internal tint header being #included from tint.h"
99#endif
100
101// Forward declarations
Ben Claytona7230f02022-04-11 14:37:21 +0000102namespace tint {
103class CloneContext;
104} // namespace tint
dan sinclair8155b9d2022-04-07 19:10:25 +0000105namespace tint::ast {
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000106class VariableDeclStatement;
dan sinclair8155b9d2022-04-07 19:10:25 +0000107} // namespace tint::ast
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000108
109namespace tint {
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000110
111/// ProgramBuilder is a mutable builder for a Program.
112/// To construct a Program, populate the builder and then `std::move` it to a
113/// Program.
114class ProgramBuilder {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000115 /// A helper used to disable overloads if the first type in `TYPES` is a
116 /// Source. Used to avoid ambiguities in overloads that take a Source as the
117 /// first parameter and those that perfectly-forward the first argument.
118 template <typename... TYPES>
119 using DisableIfSource =
120 traits::EnableIfIsNotType<traits::Decay<traits::NthTypeOf<0, TYPES..., void>>, Source>;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000121
dan sinclair41e4d9a2022-05-01 14:40:55 +0000122 /// VarOptionals is a helper for accepting a number of optional, extra
123 /// arguments for Var() and Global().
124 struct VarOptionals {
125 template <typename... ARGS>
126 explicit VarOptionals(ARGS&&... args) {
127 Apply(std::forward<ARGS>(args)...);
128 }
129 ~VarOptionals();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000130
dan sinclair41e4d9a2022-05-01 14:40:55 +0000131 ast::StorageClass storage = ast::StorageClass::kNone;
132 ast::Access access = ast::Access::kUndefined;
133 const ast::Expression* constructor = nullptr;
134 ast::AttributeList attributes = {};
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000135
dan sinclair41e4d9a2022-05-01 14:40:55 +0000136 private:
137 void Set(ast::StorageClass sc) { storage = sc; }
138 void Set(ast::Access ac) { access = ac; }
139 void Set(const ast::Expression* c) { constructor = c; }
140 void Set(const ast::AttributeList& l) { attributes = l; }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000141
dan sinclair41e4d9a2022-05-01 14:40:55 +0000142 template <typename FIRST, typename... ARGS>
143 void Apply(FIRST&& first, ARGS&&... args) {
144 Set(std::forward<FIRST>(first));
145 Apply(std::forward<ARGS>(args)...);
146 }
147 void Apply() {}
148 };
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000149
dan sinclair41e4d9a2022-05-01 14:40:55 +0000150 public:
151 /// ASTNodeAllocator is an alias to BlockAllocator<ast::Node>
152 using ASTNodeAllocator = utils::BlockAllocator<ast::Node>;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000153
dan sinclair41e4d9a2022-05-01 14:40:55 +0000154 /// SemNodeAllocator is an alias to BlockAllocator<sem::Node>
155 using SemNodeAllocator = utils::BlockAllocator<sem::Node>;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000156
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000157 /// Constructor
dan sinclair41e4d9a2022-05-01 14:40:55 +0000158 ProgramBuilder();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000159
dan sinclair41e4d9a2022-05-01 14:40:55 +0000160 /// Move constructor
161 /// @param rhs the builder to move
162 ProgramBuilder(ProgramBuilder&& rhs);
163
164 /// Destructor
165 virtual ~ProgramBuilder();
166
167 /// Move assignment operator
168 /// @param rhs the builder to move
169 /// @return this builder
170 ProgramBuilder& operator=(ProgramBuilder&& rhs);
171
172 /// Wrap returns a new ProgramBuilder wrapping the Program `program` without
173 /// making a deep clone of the Program contents.
174 /// ProgramBuilder returned by Wrap() is intended to temporarily extend an
175 /// existing immutable program.
176 /// As the returned ProgramBuilder wraps `program`, `program` must not be
177 /// destructed or assigned while using the returned ProgramBuilder.
178 /// TODO(bclayton) - Evaluate whether there are safer alternatives to this
179 /// function. See crbug.com/tint/460.
180 /// @param program the immutable Program to wrap
181 /// @return the ProgramBuilder that wraps `program`
182 static ProgramBuilder Wrap(const Program* program);
183
184 /// @returns the unique identifier for this program
185 ProgramID ID() const { return id_; }
186
187 /// @returns a reference to the program's types
188 sem::Manager& Types() {
189 AssertNotMoved();
190 return types_;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000191 }
192
dan sinclair41e4d9a2022-05-01 14:40:55 +0000193 /// @returns a reference to the program's types
194 const sem::Manager& Types() const {
195 AssertNotMoved();
196 return types_;
197 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000198
dan sinclair41e4d9a2022-05-01 14:40:55 +0000199 /// @returns a reference to the program's AST nodes storage
200 ASTNodeAllocator& ASTNodes() {
201 AssertNotMoved();
202 return ast_nodes_;
203 }
204
205 /// @returns a reference to the program's AST nodes storage
206 const ASTNodeAllocator& ASTNodes() const {
207 AssertNotMoved();
208 return ast_nodes_;
209 }
210
211 /// @returns a reference to the program's semantic nodes storage
212 SemNodeAllocator& SemNodes() {
213 AssertNotMoved();
214 return sem_nodes_;
215 }
216
217 /// @returns a reference to the program's semantic nodes storage
218 const SemNodeAllocator& SemNodes() const {
219 AssertNotMoved();
220 return sem_nodes_;
221 }
222
223 /// @returns a reference to the program's AST root Module
224 ast::Module& AST() {
225 AssertNotMoved();
226 return *ast_;
227 }
228
229 /// @returns a reference to the program's AST root Module
230 const ast::Module& AST() const {
231 AssertNotMoved();
232 return *ast_;
233 }
234
235 /// @returns a reference to the program's semantic info
236 sem::Info& Sem() {
237 AssertNotMoved();
238 return sem_;
239 }
240
241 /// @returns a reference to the program's semantic info
242 const sem::Info& Sem() const {
243 AssertNotMoved();
244 return sem_;
245 }
246
247 /// @returns a reference to the program's SymbolTable
248 SymbolTable& Symbols() {
249 AssertNotMoved();
250 return symbols_;
251 }
252
253 /// @returns a reference to the program's SymbolTable
254 const SymbolTable& Symbols() const {
255 AssertNotMoved();
256 return symbols_;
257 }
258
259 /// @returns a reference to the program's diagnostics
260 diag::List& Diagnostics() {
261 AssertNotMoved();
262 return diagnostics_;
263 }
264
265 /// @returns a reference to the program's diagnostics
266 const diag::List& Diagnostics() const {
267 AssertNotMoved();
268 return diagnostics_;
269 }
270
271 /// Controls whether the Resolver will be run on the program when it is built.
272 /// @param enable the new flag value (defaults to true)
273 void SetResolveOnBuild(bool enable) { resolve_on_build_ = enable; }
274
275 /// @return true if the Resolver will be run on the program when it is
276 /// built.
277 bool ResolveOnBuild() const { return resolve_on_build_; }
278
279 /// @returns true if the program has no error diagnostics and is not missing
280 /// information
281 bool IsValid() const;
282
283 /// Creates a new ast::Node owned by the ProgramBuilder. When the
284 /// ProgramBuilder is destructed, the ast::Node will also be destructed.
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000285 /// @param source the Source of the node
dan sinclair41e4d9a2022-05-01 14:40:55 +0000286 /// @param args the arguments to pass to the type constructor
287 /// @returns the node pointer
288 template <typename T, typename... ARGS>
289 traits::EnableIfIsType<T, ast::Node>* create(const Source& source, ARGS&&... args) {
290 AssertNotMoved();
291 return ast_nodes_.Create<T>(id_, source, std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000292 }
293
dan sinclair41e4d9a2022-05-01 14:40:55 +0000294 /// Creates a new ast::Node owned by the ProgramBuilder, injecting the current
295 /// Source as set by the last call to SetSource() as the only argument to the
296 /// constructor.
297 /// When the ProgramBuilder is destructed, the ast::Node will also be
298 /// destructed.
299 /// @returns the node pointer
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000300 template <typename T>
dan sinclair41e4d9a2022-05-01 14:40:55 +0000301 traits::EnableIfIsType<T, ast::Node>* create() {
302 AssertNotMoved();
303 return ast_nodes_.Create<T>(id_, source_);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000304 }
305
dan sinclair41e4d9a2022-05-01 14:40:55 +0000306 /// Creates a new ast::Node owned by the ProgramBuilder, injecting the current
307 /// Source as set by the last call to SetSource() as the first argument to the
308 /// constructor.
309 /// When the ProgramBuilder is destructed, the ast::Node will also be
310 /// destructed.
311 /// @param arg0 the first arguments to pass to the type constructor
312 /// @param args the remaining arguments to pass to the type constructor
313 /// @returns the node pointer
314 template <typename T, typename ARG0, typename... ARGS>
315 traits::EnableIf</* T is ast::Node and ARG0 is not Source */
316 traits::IsTypeOrDerived<T, ast::Node> &&
317 !traits::IsTypeOrDerived<ARG0, Source>,
318 T>*
319 create(ARG0&& arg0, ARGS&&... args) {
320 AssertNotMoved();
321 return ast_nodes_.Create<T>(id_, source_, std::forward<ARG0>(arg0),
322 std::forward<ARGS>(args)...);
323 }
324
325 /// Creates a new sem::Node owned by the ProgramBuilder.
326 /// When the ProgramBuilder is destructed, the sem::Node will also be
327 /// destructed.
328 /// @param args the arguments to pass to the type constructor
329 /// @returns the node pointer
330 template <typename T, typename... ARGS>
331 traits::EnableIf<traits::IsTypeOrDerived<T, sem::Node> &&
332 !traits::IsTypeOrDerived<T, sem::Type>,
333 T>*
334 create(ARGS&&... args) {
335 AssertNotMoved();
336 return sem_nodes_.Create<T>(std::forward<ARGS>(args)...);
337 }
338
339 /// Creates a new sem::Type owned by the ProgramBuilder.
340 /// When the ProgramBuilder is destructed, owned ProgramBuilder and the
341 /// returned`Type` will also be destructed.
342 /// Types are unique (de-aliased), and so calling create() for the same `T`
343 /// and arguments will return the same pointer.
344 /// @warning Use this method to acquire a type only if all of its type
345 /// information is provided in the constructor arguments `args`.<br>
346 /// If the type requires additional configuration after construction that
347 /// affect its fundamental type, build the type with `std::make_unique`, make
348 /// any necessary alterations and then call unique_type() instead.
349 /// @param args the arguments to pass to the type constructor
350 /// @returns the de-aliased type pointer
351 template <typename T, typename... ARGS>
352 traits::EnableIfIsType<T, sem::Type>* create(ARGS&&... args) {
353 static_assert(std::is_base_of<sem::Type, T>::value, "T does not derive from sem::Type");
354 AssertNotMoved();
355 return types_.Get<T>(std::forward<ARGS>(args)...);
356 }
357
358 /// Marks this builder as moved, preventing any further use of the builder.
359 void MarkAsMoved();
360
361 //////////////////////////////////////////////////////////////////////////////
362 // TypesBuilder
363 //////////////////////////////////////////////////////////////////////////////
364
365 /// TypesBuilder holds basic `tint` types and methods for constructing
366 /// complex types.
367 class TypesBuilder {
368 public:
369 /// Constructor
370 /// @param builder the program builder
371 explicit TypesBuilder(ProgramBuilder* builder);
372
373 /// @return the tint AST type for the C type `T`.
374 template <typename T>
375 const ast::Type* Of() const {
376 return CToAST<T>::get(this);
377 }
378
379 /// @returns a boolean type
380 const ast::Bool* bool_() const { return builder->create<ast::Bool>(); }
381
382 /// @param source the Source of the node
383 /// @returns a boolean type
384 const ast::Bool* bool_(const Source& source) const {
385 return builder->create<ast::Bool>(source);
386 }
387
388 /// @returns a f32 type
389 const ast::F32* f32() const { return builder->create<ast::F32>(); }
390
391 /// @param source the Source of the node
392 /// @returns a f32 type
393 const ast::F32* f32(const Source& source) const {
394 return builder->create<ast::F32>(source);
395 }
396
397 /// @returns a i32 type
398 const ast::I32* i32() const { return builder->create<ast::I32>(); }
399
400 /// @param source the Source of the node
401 /// @returns a i32 type
402 const ast::I32* i32(const Source& source) const {
403 return builder->create<ast::I32>(source);
404 }
405
406 /// @returns a u32 type
407 const ast::U32* u32() const { return builder->create<ast::U32>(); }
408
409 /// @param source the Source of the node
410 /// @returns a u32 type
411 const ast::U32* u32(const Source& source) const {
412 return builder->create<ast::U32>(source);
413 }
414
415 /// @returns a void type
416 const ast::Void* void_() const { return builder->create<ast::Void>(); }
417
418 /// @param source the Source of the node
419 /// @returns a void type
420 const ast::Void* void_(const Source& source) const {
421 return builder->create<ast::Void>(source);
422 }
423
424 /// @param type vector subtype
425 /// @param n vector width in elements
426 /// @return the tint AST type for a `n`-element vector of `type`.
427 const ast::Vector* vec(const ast::Type* type, uint32_t n) const {
428 return builder->create<ast::Vector>(type, n);
429 }
430
431 /// @param source the Source of the node
432 /// @param type vector subtype
433 /// @param n vector width in elements
434 /// @return the tint AST type for a `n`-element vector of `type`.
435 const ast::Vector* vec(const Source& source, const ast::Type* type, uint32_t n) const {
436 return builder->create<ast::Vector>(source, type, n);
437 }
438
439 /// @param type vector subtype
440 /// @return the tint AST type for a 2-element vector of `type`.
441 const ast::Vector* vec2(const ast::Type* type) const { return vec(type, 2u); }
442
443 /// @param type vector subtype
444 /// @return the tint AST type for a 3-element vector of `type`.
445 const ast::Vector* vec3(const ast::Type* type) const { return vec(type, 3u); }
446
447 /// @param type vector subtype
448 /// @return the tint AST type for a 4-element vector of `type`.
449 const ast::Vector* vec4(const ast::Type* type) const { return vec(type, 4u); }
450
451 /// @param n vector width in elements
452 /// @return the tint AST type for a `n`-element vector of `type`.
453 template <typename T>
454 const ast::Vector* vec(uint32_t n) const {
455 return vec(Of<T>(), n);
456 }
457
458 /// @return the tint AST type for a 2-element vector of the C type `T`.
459 template <typename T>
460 const ast::Vector* vec2() const {
461 return vec2(Of<T>());
462 }
463
464 /// @return the tint AST type for a 3-element vector of the C type `T`.
465 template <typename T>
466 const ast::Vector* vec3() const {
467 return vec3(Of<T>());
468 }
469
470 /// @return the tint AST type for a 4-element vector of the C type `T`.
471 template <typename T>
472 const ast::Vector* vec4() const {
473 return vec4(Of<T>());
474 }
475
476 /// @param type matrix subtype
477 /// @param columns number of columns for the matrix
478 /// @param rows number of rows for the matrix
479 /// @return the tint AST type for a matrix of `type`
480 const ast::Matrix* mat(const ast::Type* type, uint32_t columns, uint32_t rows) const {
481 return builder->create<ast::Matrix>(type, rows, columns);
482 }
483
484 /// @param source the Source of the node
485 /// @param type matrix subtype
486 /// @param columns number of columns for the matrix
487 /// @param rows number of rows for the matrix
488 /// @return the tint AST type for a matrix of `type`
489 const ast::Matrix* mat(const Source& source,
490 const ast::Type* type,
491 uint32_t columns,
492 uint32_t rows) const {
493 return builder->create<ast::Matrix>(source, type, rows, columns);
494 }
495
496 /// @param type matrix subtype
497 /// @return the tint AST type for a 2x3 matrix of `type`.
498 const ast::Matrix* mat2x2(const ast::Type* type) const { return mat(type, 2u, 2u); }
499
500 /// @param type matrix subtype
501 /// @return the tint AST type for a 2x3 matrix of `type`.
502 const ast::Matrix* mat2x3(const ast::Type* type) const { return mat(type, 2u, 3u); }
503
504 /// @param type matrix subtype
505 /// @return the tint AST type for a 2x4 matrix of `type`.
506 const ast::Matrix* mat2x4(const ast::Type* type) const { return mat(type, 2u, 4u); }
507
508 /// @param type matrix subtype
509 /// @return the tint AST type for a 3x2 matrix of `type`.
510 const ast::Matrix* mat3x2(const ast::Type* type) const { return mat(type, 3u, 2u); }
511
512 /// @param type matrix subtype
513 /// @return the tint AST type for a 3x3 matrix of `type`.
514 const ast::Matrix* mat3x3(const ast::Type* type) const { return mat(type, 3u, 3u); }
515
516 /// @param type matrix subtype
517 /// @return the tint AST type for a 3x4 matrix of `type`.
518 const ast::Matrix* mat3x4(const ast::Type* type) const { return mat(type, 3u, 4u); }
519
520 /// @param type matrix subtype
521 /// @return the tint AST type for a 4x2 matrix of `type`.
522 const ast::Matrix* mat4x2(const ast::Type* type) const { return mat(type, 4u, 2u); }
523
524 /// @param type matrix subtype
525 /// @return the tint AST type for a 4x3 matrix of `type`.
526 const ast::Matrix* mat4x3(const ast::Type* type) const { return mat(type, 4u, 3u); }
527
528 /// @param type matrix subtype
529 /// @return the tint AST type for a 4x4 matrix of `type`.
530 const ast::Matrix* mat4x4(const ast::Type* type) const { return mat(type, 4u, 4u); }
531
532 /// @param columns number of columns for the matrix
533 /// @param rows number of rows for the matrix
534 /// @return the tint AST type for a matrix of `type`
535 template <typename T>
536 const ast::Matrix* mat(uint32_t columns, uint32_t rows) const {
537 return mat(Of<T>(), columns, rows);
538 }
539
540 /// @return the tint AST type for a 2x3 matrix of the C type `T`.
541 template <typename T>
542 const ast::Matrix* mat2x2() const {
543 return mat2x2(Of<T>());
544 }
545
546 /// @return the tint AST type for a 2x3 matrix of the C type `T`.
547 template <typename T>
548 const ast::Matrix* mat2x3() const {
549 return mat2x3(Of<T>());
550 }
551
552 /// @return the tint AST type for a 2x4 matrix of the C type `T`.
553 template <typename T>
554 const ast::Matrix* mat2x4() const {
555 return mat2x4(Of<T>());
556 }
557
558 /// @return the tint AST type for a 3x2 matrix of the C type `T`.
559 template <typename T>
560 const ast::Matrix* mat3x2() const {
561 return mat3x2(Of<T>());
562 }
563
564 /// @return the tint AST type for a 3x3 matrix of the C type `T`.
565 template <typename T>
566 const ast::Matrix* mat3x3() const {
567 return mat3x3(Of<T>());
568 }
569
570 /// @return the tint AST type for a 3x4 matrix of the C type `T`.
571 template <typename T>
572 const ast::Matrix* mat3x4() const {
573 return mat3x4(Of<T>());
574 }
575
576 /// @return the tint AST type for a 4x2 matrix of the C type `T`.
577 template <typename T>
578 const ast::Matrix* mat4x2() const {
579 return mat4x2(Of<T>());
580 }
581
582 /// @return the tint AST type for a 4x3 matrix of the C type `T`.
583 template <typename T>
584 const ast::Matrix* mat4x3() const {
585 return mat4x3(Of<T>());
586 }
587
588 /// @return the tint AST type for a 4x4 matrix of the C type `T`.
589 template <typename T>
590 const ast::Matrix* mat4x4() const {
591 return mat4x4(Of<T>());
592 }
593
594 /// @param subtype the array element type
595 /// @param n the array size. nullptr represents a runtime-array
596 /// @param attrs the optional attributes for the array
597 /// @return the tint AST type for a array of size `n` of type `T`
598 template <typename EXPR = ast::Expression*>
599 const ast::Array* array(const ast::Type* subtype,
600 EXPR&& n = nullptr,
601 ast::AttributeList attrs = {}) const {
602 return builder->create<ast::Array>(subtype, builder->Expr(std::forward<EXPR>(n)),
603 attrs);
604 }
605
606 /// @param source the Source of the node
607 /// @param subtype the array element type
608 /// @param n the array size. nullptr represents a runtime-array
609 /// @param attrs the optional attributes for the array
610 /// @return the tint AST type for a array of size `n` of type `T`
611 template <typename EXPR = ast::Expression*>
612 const ast::Array* array(const Source& source,
613 const ast::Type* subtype,
614 EXPR&& n = nullptr,
615 ast::AttributeList attrs = {}) const {
616 return builder->create<ast::Array>(source, subtype,
617 builder->Expr(std::forward<EXPR>(n)), attrs);
618 }
619
620 /// @param subtype the array element type
621 /// @param n the array size. nullptr represents a runtime-array
622 /// @param stride the array stride. 0 represents implicit stride
623 /// @return the tint AST type for a array of size `n` of type `T`
624 template <typename EXPR>
625 const ast::Array* array(const ast::Type* subtype, EXPR&& n, uint32_t stride) const {
626 ast::AttributeList attrs;
627 if (stride) {
628 attrs.emplace_back(builder->create<ast::StrideAttribute>(stride));
629 }
630 return array(subtype, std::forward<EXPR>(n), std::move(attrs));
631 }
632
633 /// @param source the Source of the node
634 /// @param subtype the array element type
635 /// @param n the array size. nullptr represents a runtime-array
636 /// @param stride the array stride. 0 represents implicit stride
637 /// @return the tint AST type for a array of size `n` of type `T`
638 template <typename EXPR>
639 const ast::Array* array(const Source& source,
640 const ast::Type* subtype,
641 EXPR&& n,
642 uint32_t stride) const {
643 ast::AttributeList attrs;
644 if (stride) {
645 attrs.emplace_back(builder->create<ast::StrideAttribute>(stride));
646 }
647 return array(source, subtype, std::forward<EXPR>(n), std::move(attrs));
648 }
649
650 /// @return the tint AST type for a runtime-sized array of type `T`
651 template <typename T>
652 const ast::Array* array() const {
653 return array(Of<T>(), nullptr);
654 }
655
656 /// @return the tint AST type for an array of size `N` of type `T`
657 template <typename T, int N>
658 const ast::Array* array() const {
Ben Clayton0ce9ab02022-05-05 20:23:40 +0000659 return array(Of<T>(), builder->Expr(tint::u32(N)));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000660 }
661
662 /// @param stride the array stride
663 /// @return the tint AST type for a runtime-sized array of type `T`
664 template <typename T>
665 const ast::Array* array(uint32_t stride) const {
666 return array(Of<T>(), nullptr, stride);
667 }
668
669 /// @param stride the array stride
670 /// @return the tint AST type for an array of size `N` of type `T`
671 template <typename T, int N>
672 const ast::Array* array(uint32_t stride) const {
Ben Clayton0ce9ab02022-05-05 20:23:40 +0000673 return array(Of<T>(), builder->Expr(tint::u32(N)), stride);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000674 }
675
676 /// Creates a type name
677 /// @param name the name
678 /// @returns the type name
679 template <typename NAME>
680 const ast::TypeName* type_name(NAME&& name) const {
681 return builder->create<ast::TypeName>(builder->Sym(std::forward<NAME>(name)));
682 }
683
684 /// Creates a type name
685 /// @param source the Source of the node
686 /// @param name the name
687 /// @returns the type name
688 template <typename NAME>
689 const ast::TypeName* type_name(const Source& source, NAME&& name) const {
690 return builder->create<ast::TypeName>(source, builder->Sym(std::forward<NAME>(name)));
691 }
692
693 /// Creates an alias type
694 /// @param name the alias name
695 /// @param type the alias type
696 /// @returns the alias pointer
697 template <typename NAME>
698 const ast::Alias* alias(NAME&& name, const ast::Type* type) const {
699 auto sym = builder->Sym(std::forward<NAME>(name));
700 return builder->create<ast::Alias>(sym, type);
701 }
702
703 /// Creates an alias type
704 /// @param source the Source of the node
705 /// @param name the alias name
706 /// @param type the alias type
707 /// @returns the alias pointer
708 template <typename NAME>
709 const ast::Alias* alias(const Source& source, NAME&& name, const ast::Type* type) const {
710 auto sym = builder->Sym(std::forward<NAME>(name));
711 return builder->create<ast::Alias>(source, sym, type);
712 }
713
714 /// @param type the type of the pointer
715 /// @param storage_class the storage class of the pointer
716 /// @param access the optional access control of the pointer
717 /// @return the pointer to `type` with the given ast::StorageClass
718 const ast::Pointer* pointer(const ast::Type* type,
719 ast::StorageClass storage_class,
720 ast::Access access = ast::Access::kUndefined) const {
721 return builder->create<ast::Pointer>(type, storage_class, access);
722 }
723
724 /// @param source the Source of the node
725 /// @param type the type of the pointer
726 /// @param storage_class the storage class of the pointer
727 /// @param access the optional access control of the pointer
728 /// @return the pointer to `type` with the given ast::StorageClass
729 const ast::Pointer* pointer(const Source& source,
730 const ast::Type* type,
731 ast::StorageClass storage_class,
732 ast::Access access = ast::Access::kUndefined) const {
733 return builder->create<ast::Pointer>(source, type, storage_class, access);
734 }
735
736 /// @param storage_class the storage class of the pointer
737 /// @param access the optional access control of the pointer
738 /// @return the pointer to type `T` with the given ast::StorageClass.
739 template <typename T>
740 const ast::Pointer* pointer(ast::StorageClass storage_class,
741 ast::Access access = ast::Access::kUndefined) const {
742 return pointer(Of<T>(), storage_class, access);
743 }
744
745 /// @param source the Source of the node
746 /// @param type the type of the atomic
747 /// @return the atomic to `type`
748 const ast::Atomic* atomic(const Source& source, const ast::Type* type) const {
749 return builder->create<ast::Atomic>(source, type);
750 }
751
752 /// @param type the type of the atomic
753 /// @return the atomic to `type`
754 const ast::Atomic* atomic(const ast::Type* type) const {
755 return builder->create<ast::Atomic>(type);
756 }
757
758 /// @return the atomic to type `T`
759 template <typename T>
760 const ast::Atomic* atomic() const {
761 return atomic(Of<T>());
762 }
763
764 /// @param kind the kind of sampler
765 /// @returns the sampler
766 const ast::Sampler* sampler(ast::SamplerKind kind) const {
767 return builder->create<ast::Sampler>(kind);
768 }
769
770 /// @param source the Source of the node
771 /// @param kind the kind of sampler
772 /// @returns the sampler
773 const ast::Sampler* sampler(const Source& source, ast::SamplerKind kind) const {
774 return builder->create<ast::Sampler>(source, kind);
775 }
776
777 /// @param dims the dimensionality of the texture
778 /// @returns the depth texture
779 const ast::DepthTexture* depth_texture(ast::TextureDimension dims) const {
780 return builder->create<ast::DepthTexture>(dims);
781 }
782
783 /// @param source the Source of the node
784 /// @param dims the dimensionality of the texture
785 /// @returns the depth texture
786 const ast::DepthTexture* depth_texture(const Source& source,
787 ast::TextureDimension dims) const {
788 return builder->create<ast::DepthTexture>(source, dims);
789 }
790
791 /// @param dims the dimensionality of the texture
792 /// @returns the multisampled depth texture
793 const ast::DepthMultisampledTexture* depth_multisampled_texture(
794 ast::TextureDimension dims) const {
795 return builder->create<ast::DepthMultisampledTexture>(dims);
796 }
797
798 /// @param source the Source of the node
799 /// @param dims the dimensionality of the texture
800 /// @returns the multisampled depth texture
801 const ast::DepthMultisampledTexture* depth_multisampled_texture(
802 const Source& source,
803 ast::TextureDimension dims) const {
804 return builder->create<ast::DepthMultisampledTexture>(source, dims);
805 }
806
807 /// @param dims the dimensionality of the texture
808 /// @param subtype the texture subtype.
809 /// @returns the sampled texture
810 const ast::SampledTexture* sampled_texture(ast::TextureDimension dims,
811 const ast::Type* subtype) const {
812 return builder->create<ast::SampledTexture>(dims, subtype);
813 }
814
815 /// @param source the Source of the node
816 /// @param dims the dimensionality of the texture
817 /// @param subtype the texture subtype.
818 /// @returns the sampled texture
819 const ast::SampledTexture* sampled_texture(const Source& source,
820 ast::TextureDimension dims,
821 const ast::Type* subtype) const {
822 return builder->create<ast::SampledTexture>(source, dims, subtype);
823 }
824
825 /// @param dims the dimensionality of the texture
826 /// @param subtype the texture subtype.
827 /// @returns the multisampled texture
828 const ast::MultisampledTexture* multisampled_texture(ast::TextureDimension dims,
829 const ast::Type* subtype) const {
830 return builder->create<ast::MultisampledTexture>(dims, subtype);
831 }
832
833 /// @param source the Source of the node
834 /// @param dims the dimensionality of the texture
835 /// @param subtype the texture subtype.
836 /// @returns the multisampled texture
837 const ast::MultisampledTexture* multisampled_texture(const Source& source,
838 ast::TextureDimension dims,
839 const ast::Type* subtype) const {
840 return builder->create<ast::MultisampledTexture>(source, dims, subtype);
841 }
842
843 /// @param dims the dimensionality of the texture
844 /// @param format the texel format of the texture
845 /// @param access the access control of the texture
846 /// @returns the storage texture
847 const ast::StorageTexture* storage_texture(ast::TextureDimension dims,
848 ast::TexelFormat format,
849 ast::Access access) const {
850 auto* subtype = ast::StorageTexture::SubtypeFor(format, *builder);
851 return builder->create<ast::StorageTexture>(dims, format, subtype, access);
852 }
853
854 /// @param source the Source of the node
855 /// @param dims the dimensionality of the texture
856 /// @param format the texel format of the texture
857 /// @param access the access control of the texture
858 /// @returns the storage texture
859 const ast::StorageTexture* storage_texture(const Source& source,
860 ast::TextureDimension dims,
861 ast::TexelFormat format,
862 ast::Access access) const {
863 auto* subtype = ast::StorageTexture::SubtypeFor(format, *builder);
864 return builder->create<ast::StorageTexture>(source, dims, format, subtype, access);
865 }
866
867 /// @returns the external texture
868 const ast::ExternalTexture* external_texture() const {
869 return builder->create<ast::ExternalTexture>();
870 }
871
872 /// @param source the Source of the node
873 /// @returns the external texture
874 const ast::ExternalTexture* external_texture(const Source& source) const {
875 return builder->create<ast::ExternalTexture>(source);
876 }
877
878 /// Constructs a TypeName for the type declaration.
879 /// @param type the type
880 /// @return either type or a pointer to a new ast::TypeName
881 const ast::TypeName* Of(const ast::TypeDecl* type) const;
882
883 /// The ProgramBuilder
884 ProgramBuilder* const builder;
885
886 private:
887 /// CToAST<T> is specialized for various `T` types and each specialization
888 /// contains a single static `get()` method for obtaining the corresponding
889 /// AST type for the C type `T`.
890 /// `get()` has the signature:
891 /// `static const ast::Type* get(Types* t)`
892 template <typename T>
893 struct CToAST {};
894 };
895
896 //////////////////////////////////////////////////////////////////////////////
897 // AST helper methods
898 //////////////////////////////////////////////////////////////////////////////
899
900 /// @return a new unnamed symbol
901 Symbol Sym() { return Symbols().New(); }
902
903 /// @param name the symbol string
904 /// @return a Symbol with the given name
905 Symbol Sym(const std::string& name) { return Symbols().Register(name); }
906
907 /// @param sym the symbol
908 /// @return `sym`
909 Symbol Sym(Symbol sym) { return sym; }
910
911 /// @param expr the expression
912 /// @return expr
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000913 template <typename T>
dan sinclair41e4d9a2022-05-01 14:40:55 +0000914 traits::EnableIfIsType<T, ast::Expression>* Expr(T* expr) {
915 return expr;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000916 }
917
dan sinclair41e4d9a2022-05-01 14:40:55 +0000918 /// Passthrough for nullptr
919 /// @return nullptr
920 const ast::IdentifierExpression* Expr(std::nullptr_t) { return nullptr; }
921
922 /// @param source the source information
923 /// @param symbol the identifier symbol
924 /// @return an ast::IdentifierExpression with the given symbol
925 const ast::IdentifierExpression* Expr(const Source& source, Symbol symbol) {
926 return create<ast::IdentifierExpression>(source, symbol);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000927 }
928
dan sinclair41e4d9a2022-05-01 14:40:55 +0000929 /// @param symbol the identifier symbol
930 /// @return an ast::IdentifierExpression with the given symbol
931 const ast::IdentifierExpression* Expr(Symbol symbol) {
932 return create<ast::IdentifierExpression>(symbol);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000933 }
934
dan sinclair41e4d9a2022-05-01 14:40:55 +0000935 /// @param source the source information
936 /// @param variable the AST variable
937 /// @return an ast::IdentifierExpression with the variable's symbol
938 const ast::IdentifierExpression* Expr(const Source& source, const ast::Variable* variable) {
939 return create<ast::IdentifierExpression>(source, variable->symbol);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000940 }
941
dan sinclair41e4d9a2022-05-01 14:40:55 +0000942 /// @param variable the AST variable
943 /// @return an ast::IdentifierExpression with the variable's symbol
944 const ast::IdentifierExpression* Expr(const ast::Variable* variable) {
945 return create<ast::IdentifierExpression>(variable->symbol);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000946 }
947
dan sinclair41e4d9a2022-05-01 14:40:55 +0000948 /// @param source the source information
949 /// @param name the identifier name
950 /// @return an ast::IdentifierExpression with the given name
951 const ast::IdentifierExpression* Expr(const Source& source, const char* name) {
952 return create<ast::IdentifierExpression>(source, Symbols().Register(name));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000953 }
954
dan sinclair41e4d9a2022-05-01 14:40:55 +0000955 /// @param name the identifier name
956 /// @return an ast::IdentifierExpression with the given name
957 const ast::IdentifierExpression* Expr(const char* name) {
958 return create<ast::IdentifierExpression>(Symbols().Register(name));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000959 }
960
dan sinclair41e4d9a2022-05-01 14:40:55 +0000961 /// @param source the source information
962 /// @param name the identifier name
963 /// @return an ast::IdentifierExpression with the given name
964 const ast::IdentifierExpression* Expr(const Source& source, const std::string& name) {
965 return create<ast::IdentifierExpression>(source, Symbols().Register(name));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000966 }
967
dan sinclair41e4d9a2022-05-01 14:40:55 +0000968 /// @param name the identifier name
969 /// @return an ast::IdentifierExpression with the given name
970 const ast::IdentifierExpression* Expr(const std::string& name) {
971 return create<ast::IdentifierExpression>(Symbols().Register(name));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000972 }
973
dan sinclair41e4d9a2022-05-01 14:40:55 +0000974 /// @param source the source information
975 /// @param value the boolean value
976 /// @return a Scalar constructor for the given value
977 const ast::BoolLiteralExpression* Expr(const Source& source, bool value) {
978 return create<ast::BoolLiteralExpression>(source, value);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000979 }
980
dan sinclair41e4d9a2022-05-01 14:40:55 +0000981 /// @param value the boolean value
982 /// @return a Scalar constructor for the given value
983 const ast::BoolLiteralExpression* Expr(bool value) {
984 return create<ast::BoolLiteralExpression>(value);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000985 }
986
dan sinclair41e4d9a2022-05-01 14:40:55 +0000987 /// @param source the source information
988 /// @param value the float value
989 /// @return a Scalar constructor for the given value
990 const ast::FloatLiteralExpression* Expr(const Source& source, f32 value) {
991 return create<ast::FloatLiteralExpression>(source, value);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000992 }
993
dan sinclair41e4d9a2022-05-01 14:40:55 +0000994 /// @param value the float value
995 /// @return a Scalar constructor for the given value
996 const ast::FloatLiteralExpression* Expr(f32 value) {
997 return create<ast::FloatLiteralExpression>(value);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000998 }
999
dan sinclair41e4d9a2022-05-01 14:40:55 +00001000 /// @param source the source information
1001 /// @param value the integer value
Ben Clayton0ce9ab02022-05-05 20:23:40 +00001002 /// @return a 'i'-suffixed IntLiteralExpression for the given value
Ben Clayton8822e292022-05-04 22:18:49 +00001003 const ast::IntLiteralExpression* Expr(const Source& source, i32 value) {
1004 return create<ast::IntLiteralExpression>(source, value,
Ben Clayton0ce9ab02022-05-05 20:23:40 +00001005 ast::IntLiteralExpression::Suffix::kI);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001006 }
1007
dan sinclair41e4d9a2022-05-01 14:40:55 +00001008 /// @param value the integer value
Ben Clayton0ce9ab02022-05-05 20:23:40 +00001009 /// @return a 'i'-suffixed IntLiteralExpression for the given value
Ben Clayton8822e292022-05-04 22:18:49 +00001010 const ast::IntLiteralExpression* Expr(i32 value) {
Ben Clayton0ce9ab02022-05-05 20:23:40 +00001011 return create<ast::IntLiteralExpression>(value, ast::IntLiteralExpression::Suffix::kI);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001012 }
1013
dan sinclair41e4d9a2022-05-01 14:40:55 +00001014 /// @param source the source information
1015 /// @param value the unsigned int value
Ben Clayton0ce9ab02022-05-05 20:23:40 +00001016 /// @return a 'u'-suffixed IntLiteralExpression for the given value
Ben Clayton8822e292022-05-04 22:18:49 +00001017 const ast::IntLiteralExpression* Expr(const Source& source, u32 value) {
1018 return create<ast::IntLiteralExpression>(source, value,
1019 ast::IntLiteralExpression::Suffix::kU);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001020 }
1021
dan sinclair41e4d9a2022-05-01 14:40:55 +00001022 /// @param value the unsigned int value
Ben Clayton0ce9ab02022-05-05 20:23:40 +00001023 /// @return a 'u'-suffixed IntLiteralExpression for the given value
Ben Clayton8822e292022-05-04 22:18:49 +00001024 const ast::IntLiteralExpression* Expr(u32 value) {
1025 return create<ast::IntLiteralExpression>(value, ast::IntLiteralExpression::Suffix::kU);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001026 }
1027
dan sinclair41e4d9a2022-05-01 14:40:55 +00001028 /// Converts `arg` to an `ast::Expression` using `Expr()`, then appends it to
1029 /// `list`.
1030 /// @param list the list to append too
1031 /// @param arg the arg to create
1032 template <typename ARG>
1033 void Append(ast::ExpressionList& list, ARG&& arg) {
1034 list.emplace_back(Expr(std::forward<ARG>(arg)));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001035 }
1036
dan sinclair41e4d9a2022-05-01 14:40:55 +00001037 /// Converts `arg0` and `args` to `ast::Expression`s using `Expr()`,
1038 /// then appends them to `list`.
1039 /// @param list the list to append too
1040 /// @param arg0 the first argument
1041 /// @param args the rest of the arguments
1042 template <typename ARG0, typename... ARGS>
1043 void Append(ast::ExpressionList& list, ARG0&& arg0, ARGS&&... args) {
1044 Append(list, std::forward<ARG0>(arg0));
1045 Append(list, std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001046 }
1047
dan sinclair41e4d9a2022-05-01 14:40:55 +00001048 /// @return an empty list of expressions
1049 ast::ExpressionList ExprList() { return {}; }
1050
1051 /// @param args the list of expressions
1052 /// @return the list of expressions converted to `ast::Expression`s using
1053 /// `Expr()`,
1054 template <typename... ARGS>
1055 ast::ExpressionList ExprList(ARGS&&... args) {
1056 ast::ExpressionList list;
1057 list.reserve(sizeof...(args));
1058 Append(list, std::forward<ARGS>(args)...);
1059 return list;
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001060 }
1061
dan sinclair41e4d9a2022-05-01 14:40:55 +00001062 /// @param list the list of expressions
1063 /// @return `list`
1064 ast::ExpressionList ExprList(ast::ExpressionList list) { return list; }
1065
1066 /// @param args the arguments for the type constructor
1067 /// @return an `ast::CallExpression` of type `ty`, with the values
1068 /// of `args` converted to `ast::Expression`s using `Expr()`
1069 template <typename T, typename... ARGS>
1070 const ast::CallExpression* Construct(ARGS&&... args) {
1071 return Construct(ty.Of<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001072 }
1073
dan sinclair41e4d9a2022-05-01 14:40:55 +00001074 /// @param type the type to construct
1075 /// @param args the arguments for the constructor
1076 /// @return an `ast::CallExpression` of `type` constructed with the
1077 /// values `args`.
1078 template <typename... ARGS>
1079 const ast::CallExpression* Construct(const ast::Type* type, ARGS&&... args) {
1080 return Construct(source_, type, std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001081 }
1082
dan sinclair41e4d9a2022-05-01 14:40:55 +00001083 /// @param source the source information
1084 /// @param type the type to construct
1085 /// @param args the arguments for the constructor
1086 /// @return an `ast::CallExpression` of `type` constructed with the
1087 /// values `args`.
1088 template <typename... ARGS>
1089 const ast::CallExpression* Construct(const Source& source,
1090 const ast::Type* type,
1091 ARGS&&... args) {
1092 return create<ast::CallExpression>(source, type, ExprList(std::forward<ARGS>(args)...));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001093 }
1094
dan sinclair41e4d9a2022-05-01 14:40:55 +00001095 /// @param expr the expression for the bitcast
1096 /// @return an `ast::BitcastExpression` of type `ty`, with the values of
1097 /// `expr` converted to `ast::Expression`s using `Expr()`
1098 template <typename T, typename EXPR>
1099 const ast::BitcastExpression* Bitcast(EXPR&& expr) {
1100 return Bitcast(ty.Of<T>(), std::forward<EXPR>(expr));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001101 }
1102
dan sinclair41e4d9a2022-05-01 14:40:55 +00001103 /// @param type the type to cast to
1104 /// @param expr the expression for the bitcast
1105 /// @return an `ast::BitcastExpression` of `type` constructed with the values
1106 /// `expr`.
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001107 template <typename EXPR>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001108 const ast::BitcastExpression* Bitcast(const ast::Type* type, EXPR&& expr) {
1109 return create<ast::BitcastExpression>(type, Expr(std::forward<EXPR>(expr)));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001110 }
1111
dan sinclair41e4d9a2022-05-01 14:40:55 +00001112 /// @param source the source information
1113 /// @param type the type to cast to
1114 /// @param expr the expression for the bitcast
1115 /// @return an `ast::BitcastExpression` of `type` constructed with the values
1116 /// `expr`.
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001117 template <typename EXPR>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001118 const ast::BitcastExpression* Bitcast(const Source& source,
1119 const ast::Type* type,
1120 EXPR&& expr) {
1121 return create<ast::BitcastExpression>(source, type, Expr(std::forward<EXPR>(expr)));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001122 }
1123
dan sinclair41e4d9a2022-05-01 14:40:55 +00001124 /// @param args the arguments for the vector constructor
1125 /// @param type the vector type
1126 /// @param size the vector size
1127 /// @return an `ast::CallExpression` of a `size`-element vector of
1128 /// type `type`, constructed with the values `args`.
1129 template <typename... ARGS>
1130 const ast::CallExpression* vec(const ast::Type* type, uint32_t size, ARGS&&... args) {
1131 return Construct(ty.vec(type, size), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001132 }
1133
dan sinclair41e4d9a2022-05-01 14:40:55 +00001134 /// @param args the arguments for the vector constructor
1135 /// @return an `ast::CallExpression` of a 2-element vector of type
1136 /// `T`, constructed with the values `args`.
1137 template <typename T, typename... ARGS>
1138 const ast::CallExpression* vec2(ARGS&&... args) {
1139 return Construct(ty.vec2<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001140 }
1141
dan sinclair41e4d9a2022-05-01 14:40:55 +00001142 /// @param args the arguments for the vector constructor
1143 /// @return an `ast::CallExpression` of a 3-element vector of type
1144 /// `T`, constructed with the values `args`.
1145 template <typename T, typename... ARGS>
1146 const ast::CallExpression* vec3(ARGS&&... args) {
1147 return Construct(ty.vec3<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001148 }
1149
dan sinclair41e4d9a2022-05-01 14:40:55 +00001150 /// @param args the arguments for the vector constructor
1151 /// @return an `ast::CallExpression` of a 4-element vector of type
1152 /// `T`, constructed with the values `args`.
1153 template <typename T, typename... ARGS>
1154 const ast::CallExpression* vec4(ARGS&&... args) {
1155 return Construct(ty.vec4<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001156 }
1157
dan sinclair41e4d9a2022-05-01 14:40:55 +00001158 /// @param args the arguments for the matrix constructor
1159 /// @return an `ast::CallExpression` of a 2x2 matrix of type
1160 /// `T`, constructed with the values `args`.
1161 template <typename T, typename... ARGS>
1162 const ast::CallExpression* mat2x2(ARGS&&... args) {
1163 return Construct(ty.mat2x2<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001164 }
1165
dan sinclair41e4d9a2022-05-01 14:40:55 +00001166 /// @param args the arguments for the matrix constructor
1167 /// @return an `ast::CallExpression` of a 2x3 matrix of type
1168 /// `T`, constructed with the values `args`.
1169 template <typename T, typename... ARGS>
1170 const ast::CallExpression* mat2x3(ARGS&&... args) {
1171 return Construct(ty.mat2x3<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001172 }
1173
dan sinclair41e4d9a2022-05-01 14:40:55 +00001174 /// @param args the arguments for the matrix constructor
1175 /// @return an `ast::CallExpression` of a 2x4 matrix of type
1176 /// `T`, constructed with the values `args`.
1177 template <typename T, typename... ARGS>
1178 const ast::CallExpression* mat2x4(ARGS&&... args) {
1179 return Construct(ty.mat2x4<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001180 }
1181
dan sinclair41e4d9a2022-05-01 14:40:55 +00001182 /// @param args the arguments for the matrix constructor
1183 /// @return an `ast::CallExpression` of a 3x2 matrix of type
1184 /// `T`, constructed with the values `args`.
1185 template <typename T, typename... ARGS>
1186 const ast::CallExpression* mat3x2(ARGS&&... args) {
1187 return Construct(ty.mat3x2<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001188 }
1189
dan sinclair41e4d9a2022-05-01 14:40:55 +00001190 /// @param args the arguments for the matrix constructor
1191 /// @return an `ast::CallExpression` of a 3x3 matrix of type
1192 /// `T`, constructed with the values `args`.
1193 template <typename T, typename... ARGS>
1194 const ast::CallExpression* mat3x3(ARGS&&... args) {
1195 return Construct(ty.mat3x3<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001196 }
1197
dan sinclair41e4d9a2022-05-01 14:40:55 +00001198 /// @param args the arguments for the matrix constructor
1199 /// @return an `ast::CallExpression` of a 3x4 matrix of type
1200 /// `T`, constructed with the values `args`.
1201 template <typename T, typename... ARGS>
1202 const ast::CallExpression* mat3x4(ARGS&&... args) {
1203 return Construct(ty.mat3x4<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001204 }
1205
dan sinclair41e4d9a2022-05-01 14:40:55 +00001206 /// @param args the arguments for the matrix constructor
1207 /// @return an `ast::CallExpression` of a 4x2 matrix of type
1208 /// `T`, constructed with the values `args`.
1209 template <typename T, typename... ARGS>
1210 const ast::CallExpression* mat4x2(ARGS&&... args) {
1211 return Construct(ty.mat4x2<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001212 }
1213
dan sinclair41e4d9a2022-05-01 14:40:55 +00001214 /// @param args the arguments for the matrix constructor
1215 /// @return an `ast::CallExpression` of a 4x3 matrix of type
1216 /// `T`, constructed with the values `args`.
1217 template <typename T, typename... ARGS>
1218 const ast::CallExpression* mat4x3(ARGS&&... args) {
1219 return Construct(ty.mat4x3<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001220 }
1221
dan sinclair41e4d9a2022-05-01 14:40:55 +00001222 /// @param args the arguments for the matrix constructor
1223 /// @return an `ast::CallExpression` of a 4x4 matrix of type
1224 /// `T`, constructed with the values `args`.
1225 template <typename T, typename... ARGS>
1226 const ast::CallExpression* mat4x4(ARGS&&... args) {
1227 return Construct(ty.mat4x4<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001228 }
1229
dan sinclair41e4d9a2022-05-01 14:40:55 +00001230 /// @param args the arguments for the array constructor
1231 /// @return an `ast::CallExpression` of an array with element type
1232 /// `T` and size `N`, constructed with the values `args`.
1233 template <typename T, int N, typename... ARGS>
1234 const ast::CallExpression* array(ARGS&&... args) {
1235 return Construct(ty.array<T, N>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001236 }
1237
dan sinclair41e4d9a2022-05-01 14:40:55 +00001238 /// @param subtype the array element type
1239 /// @param n the array size. nullptr represents a runtime-array.
1240 /// @param args the arguments for the array constructor
1241 /// @return an `ast::CallExpression` of an array with element type
1242 /// `subtype`, constructed with the values `args`.
1243 template <typename EXPR, typename... ARGS>
1244 const ast::CallExpression* array(const ast::Type* subtype, EXPR&& n, ARGS&&... args) {
1245 return Construct(ty.array(subtype, std::forward<EXPR>(n)), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001246 }
1247
dan sinclair41e4d9a2022-05-01 14:40:55 +00001248 /// @param name the variable name
1249 /// @param type the variable type
1250 /// @param optional the optional variable settings.
1251 /// Can be any of the following, in any order:
1252 /// * ast::StorageClass - specifies the variable storage class
1253 /// * ast::Access - specifies the variable's access control
1254 /// * ast::Expression* - specifies the variable's initializer expression
1255 /// * ast::AttributeList - specifies the variable's attributes
1256 /// Note that repeated arguments of the same type will use the last argument's
1257 /// value.
1258 /// @returns a `ast::Variable` with the given name, type and additional
1259 /// options
1260 template <typename NAME, typename... OPTIONAL>
1261 const ast::Variable* Var(NAME&& name, const ast::Type* type, OPTIONAL&&... optional) {
1262 VarOptionals opts(std::forward<OPTIONAL>(optional)...);
1263 return create<ast::Variable>(Sym(std::forward<NAME>(name)), opts.storage, opts.access, type,
1264 false /* is_const */, false /* is_overridable */,
1265 opts.constructor, std::move(opts.attributes));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001266 }
1267
dan sinclair41e4d9a2022-05-01 14:40:55 +00001268 /// @param source the variable source
1269 /// @param name the variable name
1270 /// @param type the variable type
1271 /// @param optional the optional variable settings.
1272 /// Can be any of the following, in any order:
1273 /// * ast::StorageClass - specifies the variable storage class
1274 /// * ast::Access - specifies the variable's access control
1275 /// * ast::Expression* - specifies the variable's initializer expression
1276 /// * ast::AttributeList - specifies the variable's attributes
1277 /// Note that repeated arguments of the same type will use the last argument's
1278 /// value.
1279 /// @returns a `ast::Variable` with the given name, storage and type
1280 template <typename NAME, typename... OPTIONAL>
1281 const ast::Variable* Var(const Source& source,
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001282 NAME&& name,
1283 const ast::Type* type,
dan sinclair41e4d9a2022-05-01 14:40:55 +00001284 OPTIONAL&&... optional) {
1285 VarOptionals opts(std::forward<OPTIONAL>(optional)...);
1286 return create<ast::Variable>(source, Sym(std::forward<NAME>(name)), opts.storage,
1287 opts.access, type, false /* is_const */,
1288 false /* is_overridable */, opts.constructor,
1289 std::move(opts.attributes));
1290 }
1291
1292 /// @param name the variable name
1293 /// @param type the variable type
1294 /// @param constructor constructor expression
1295 /// @param attributes optional variable attributes
1296 /// @returns an immutable `ast::Variable` with the given name and type
1297 template <typename NAME>
1298 const ast::Variable* Let(NAME&& name,
1299 const ast::Type* type,
1300 const ast::Expression* constructor,
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001301 ast::AttributeList attributes = {}) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001302 return create<ast::Variable>(Sym(std::forward<NAME>(name)), ast::StorageClass::kNone,
1303 ast::Access::kUndefined, type, true /* is_const */,
1304 false /* is_overridable */, constructor, attributes);
1305 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001306
dan sinclair41e4d9a2022-05-01 14:40:55 +00001307 /// @param source the variable source
1308 /// @param name the variable name
1309 /// @param type the variable type
1310 /// @param constructor constructor expression
1311 /// @param attributes optional variable attributes
1312 /// @returns an immutable `ast::Variable` with the given name and type
1313 template <typename NAME>
1314 const ast::Variable* Let(const Source& source,
1315 NAME&& name,
1316 const ast::Type* type,
1317 const ast::Expression* constructor,
1318 ast::AttributeList attributes = {}) {
1319 return create<ast::Variable>(source, Sym(std::forward<NAME>(name)),
1320 ast::StorageClass::kNone, ast::Access::kUndefined, type,
1321 true /* is_const */, false /* is_overridable */, constructor,
1322 attributes);
1323 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001324
dan sinclair41e4d9a2022-05-01 14:40:55 +00001325 /// @param name the parameter name
1326 /// @param type the parameter type
1327 /// @param attributes optional parameter attributes
1328 /// @returns an immutable `ast::Variable` with the given name and type
1329 template <typename NAME>
1330 const ast::Variable* Param(NAME&& name,
1331 const ast::Type* type,
1332 ast::AttributeList attributes = {}) {
1333 return create<ast::Variable>(Sym(std::forward<NAME>(name)), ast::StorageClass::kNone,
1334 ast::Access::kUndefined, type, true /* is_const */,
1335 false /* is_overridable */, nullptr, attributes);
1336 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001337
dan sinclair41e4d9a2022-05-01 14:40:55 +00001338 /// @param source the parameter source
1339 /// @param name the parameter name
1340 /// @param type the parameter type
1341 /// @param attributes optional parameter attributes
1342 /// @returns an immutable `ast::Variable` with the given name and type
1343 template <typename NAME>
1344 const ast::Variable* Param(const Source& source,
1345 NAME&& name,
1346 const ast::Type* type,
1347 ast::AttributeList attributes = {}) {
1348 return create<ast::Variable>(source, Sym(std::forward<NAME>(name)),
1349 ast::StorageClass::kNone, ast::Access::kUndefined, type,
1350 true /* is_const */, false /* is_overridable */, nullptr,
1351 attributes);
1352 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001353
dan sinclair41e4d9a2022-05-01 14:40:55 +00001354 /// @param name the variable name
1355 /// @param type the variable type
1356 /// @param optional the optional variable settings.
1357 /// Can be any of the following, in any order:
1358 /// * ast::StorageClass - specifies the variable storage class
1359 /// * ast::Access - specifies the variable's access control
1360 /// * ast::Expression* - specifies the variable's initializer expression
1361 /// * ast::AttributeList - specifies the variable's attributes
1362 /// Note that repeated arguments of the same type will use the last argument's
1363 /// value.
1364 /// @returns a new `ast::Variable`, which is automatically registered as a
1365 /// global variable with the ast::Module.
1366 template <typename NAME, typename... OPTIONAL, typename = DisableIfSource<NAME>>
1367 const ast::Variable* Global(NAME&& name, const ast::Type* type, OPTIONAL&&... optional) {
1368 auto* var = Var(std::forward<NAME>(name), type, std::forward<OPTIONAL>(optional)...);
1369 AST().AddGlobalVariable(var);
1370 return var;
1371 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001372
dan sinclair41e4d9a2022-05-01 14:40:55 +00001373 /// @param source the variable source
1374 /// @param name the variable name
1375 /// @param type the variable type
1376 /// @param optional the optional variable settings.
1377 /// Can be any of the following, in any order:
1378 /// * ast::StorageClass - specifies the variable storage class
1379 /// * ast::Access - specifies the variable's access control
1380 /// * ast::Expression* - specifies the variable's initializer expression
1381 /// * ast::AttributeList - specifies the variable's attributes
1382 /// Note that repeated arguments of the same type will use the last argument's
1383 /// value.
1384 /// @returns a new `ast::Variable`, which is automatically registered as a
1385 /// global variable with the ast::Module.
1386 template <typename NAME, typename... OPTIONAL>
1387 const ast::Variable* Global(const Source& source,
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001388 NAME&& name,
1389 const ast::Type* type,
dan sinclair41e4d9a2022-05-01 14:40:55 +00001390 OPTIONAL&&... optional) {
1391 auto* var =
1392 Var(source, std::forward<NAME>(name), type, std::forward<OPTIONAL>(optional)...);
1393 AST().AddGlobalVariable(var);
1394 return var;
1395 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001396
dan sinclair41e4d9a2022-05-01 14:40:55 +00001397 /// @param name the variable name
1398 /// @param type the variable type
1399 /// @param constructor constructor expression
1400 /// @param attributes optional variable attributes
1401 /// @returns a const `ast::Variable` constructed by calling Var() with the
1402 /// arguments of `args`, which is automatically registered as a global
1403 /// variable with the ast::Module.
1404 template <typename NAME>
1405 const ast::Variable* GlobalConst(NAME&& name,
1406 const ast::Type* type,
1407 const ast::Expression* constructor,
1408 ast::AttributeList attributes = {}) {
1409 auto* var = Let(std::forward<NAME>(name), type, constructor, std::move(attributes));
1410 AST().AddGlobalVariable(var);
1411 return var;
1412 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001413
dan sinclair41e4d9a2022-05-01 14:40:55 +00001414 /// @param source the variable source
1415 /// @param name the variable name
1416 /// @param type the variable type
1417 /// @param constructor constructor expression
1418 /// @param attributes optional variable attributes
1419 /// @returns a const `ast::Variable` constructed by calling Var() with the
1420 /// arguments of `args`, which is automatically registered as a global
1421 /// variable with the ast::Module.
1422 template <typename NAME>
1423 const ast::Variable* GlobalConst(const Source& source,
1424 NAME&& name,
1425 const ast::Type* type,
1426 const ast::Expression* constructor,
1427 ast::AttributeList attributes = {}) {
1428 auto* var = Let(source, std::forward<NAME>(name), type, constructor, std::move(attributes));
1429 AST().AddGlobalVariable(var);
1430 return var;
1431 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001432
dan sinclair41e4d9a2022-05-01 14:40:55 +00001433 /// @param name the variable name
1434 /// @param type the variable type
1435 /// @param constructor optional constructor expression
1436 /// @param attributes optional variable attributes
1437 /// @returns an overridable const `ast::Variable` which is automatically
1438 /// registered as a global variable with the ast::Module.
1439 template <typename NAME>
1440 const ast::Variable* Override(NAME&& name,
1441 const ast::Type* type,
1442 const ast::Expression* constructor,
1443 ast::AttributeList attributes = {}) {
1444 auto* var =
1445 create<ast::Variable>(source_, Sym(std::forward<NAME>(name)), ast::StorageClass::kNone,
1446 ast::Access::kUndefined, type, true /* is_const */,
1447 true /* is_overridable */, constructor, std::move(attributes));
1448 AST().AddGlobalVariable(var);
1449 return var;
1450 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001451
dan sinclair41e4d9a2022-05-01 14:40:55 +00001452 /// @param source the variable source
1453 /// @param name the variable name
1454 /// @param type the variable type
1455 /// @param constructor constructor expression
1456 /// @param attributes optional variable attributes
1457 /// @returns a const `ast::Variable` constructed by calling Var() with the
1458 /// arguments of `args`, which is automatically registered as a global
1459 /// variable with the ast::Module.
1460 template <typename NAME>
1461 const ast::Variable* Override(const Source& source,
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001462 NAME&& name,
1463 const ast::Type* type,
dan sinclair41e4d9a2022-05-01 14:40:55 +00001464 const ast::Expression* constructor,
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001465 ast::AttributeList attributes = {}) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001466 auto* var =
1467 create<ast::Variable>(source, Sym(std::forward<NAME>(name)), ast::StorageClass::kNone,
1468 ast::Access::kUndefined, type, true /* is_const */,
1469 true /* is_overridable */, constructor, std::move(attributes));
1470 AST().AddGlobalVariable(var);
1471 return var;
1472 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001473
dan sinclair41e4d9a2022-05-01 14:40:55 +00001474 /// @param source the source information
1475 /// @param expr the expression to take the address of
1476 /// @return an ast::UnaryOpExpression that takes the address of `expr`
1477 template <typename EXPR>
1478 const ast::UnaryOpExpression* AddressOf(const Source& source, EXPR&& expr) {
1479 return create<ast::UnaryOpExpression>(source, ast::UnaryOp::kAddressOf,
1480 Expr(std::forward<EXPR>(expr)));
1481 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001482
dan sinclair41e4d9a2022-05-01 14:40:55 +00001483 /// @param expr the expression to take the address of
1484 /// @return an ast::UnaryOpExpression that takes the address of `expr`
1485 template <typename EXPR>
1486 const ast::UnaryOpExpression* AddressOf(EXPR&& expr) {
1487 return create<ast::UnaryOpExpression>(ast::UnaryOp::kAddressOf,
1488 Expr(std::forward<EXPR>(expr)));
1489 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001490
dan sinclair41e4d9a2022-05-01 14:40:55 +00001491 /// @param source the source information
1492 /// @param expr the expression to perform an indirection on
1493 /// @return an ast::UnaryOpExpression that dereferences the pointer `expr`
1494 template <typename EXPR>
1495 const ast::UnaryOpExpression* Deref(const Source& source, EXPR&& expr) {
1496 return create<ast::UnaryOpExpression>(source, ast::UnaryOp::kIndirection,
1497 Expr(std::forward<EXPR>(expr)));
1498 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001499
dan sinclair41e4d9a2022-05-01 14:40:55 +00001500 /// @param expr the expression to perform an indirection on
1501 /// @return an ast::UnaryOpExpression that dereferences the pointer `expr`
1502 template <typename EXPR>
1503 const ast::UnaryOpExpression* Deref(EXPR&& expr) {
1504 return create<ast::UnaryOpExpression>(ast::UnaryOp::kIndirection,
1505 Expr(std::forward<EXPR>(expr)));
1506 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001507
dan sinclair41e4d9a2022-05-01 14:40:55 +00001508 /// @param expr the expression to perform a unary not on
1509 /// @return an ast::UnaryOpExpression that is the unary not of the input
1510 /// expression
1511 template <typename EXPR>
1512 const ast::UnaryOpExpression* Not(EXPR&& expr) {
1513 return create<ast::UnaryOpExpression>(ast::UnaryOp::kNot, Expr(std::forward<EXPR>(expr)));
1514 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001515
dan sinclair41e4d9a2022-05-01 14:40:55 +00001516 /// @param expr the expression to perform a unary complement on
1517 /// @return an ast::UnaryOpExpression that is the unary complement of the
1518 /// input expression
1519 template <typename EXPR>
1520 const ast::UnaryOpExpression* Complement(EXPR&& expr) {
1521 return create<ast::UnaryOpExpression>(ast::UnaryOp::kComplement,
1522 Expr(std::forward<EXPR>(expr)));
1523 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001524
Author: Shiyu Liub3aab092022-05-04 13:07:29 +00001525 /// @param expr the expression to perform a unary negation on
1526 /// @return an ast::UnaryOpExpression that is the unary negation of the
1527 /// input expression
1528 template <typename EXPR>
1529 const ast::UnaryOpExpression* Negation(EXPR&& expr) {
1530 return create<ast::UnaryOpExpression>(ast::UnaryOp::kNegation,
1531 Expr(std::forward<EXPR>(expr)));
1532 }
1533
dan sinclair41e4d9a2022-05-01 14:40:55 +00001534 /// @param source the source information
1535 /// @param func the function name
1536 /// @param args the function call arguments
1537 /// @returns a `ast::CallExpression` to the function `func`, with the
1538 /// arguments of `args` converted to `ast::Expression`s using `Expr()`.
1539 template <typename NAME, typename... ARGS>
1540 const ast::CallExpression* Call(const Source& source, NAME&& func, ARGS&&... args) {
1541 return create<ast::CallExpression>(source, Expr(func),
1542 ExprList(std::forward<ARGS>(args)...));
1543 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001544
dan sinclair41e4d9a2022-05-01 14:40:55 +00001545 /// @param func the function name
1546 /// @param args the function call arguments
1547 /// @returns a `ast::CallExpression` to the function `func`, with the
1548 /// arguments of `args` converted to `ast::Expression`s using `Expr()`.
1549 template <typename NAME, typename... ARGS, typename = DisableIfSource<NAME>>
1550 const ast::CallExpression* Call(NAME&& func, ARGS&&... args) {
1551 return create<ast::CallExpression>(Expr(func), ExprList(std::forward<ARGS>(args)...));
1552 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001553
dan sinclair41e4d9a2022-05-01 14:40:55 +00001554 /// @param source the source information
1555 /// @param call the call expression to wrap in a call statement
1556 /// @returns a `ast::CallStatement` for the given call expression
1557 const ast::CallStatement* CallStmt(const Source& source, const ast::CallExpression* call) {
1558 return create<ast::CallStatement>(source, call);
1559 }
James Pricec022ff52022-03-31 22:30:10 +00001560
dan sinclair41e4d9a2022-05-01 14:40:55 +00001561 /// @param call the call expression to wrap in a call statement
1562 /// @returns a `ast::CallStatement` for the given call expression
1563 const ast::CallStatement* CallStmt(const ast::CallExpression* call) {
1564 return create<ast::CallStatement>(call);
1565 }
James Pricec022ff52022-03-31 22:30:10 +00001566
dan sinclair41e4d9a2022-05-01 14:40:55 +00001567 /// @param source the source information
1568 /// @returns a `ast::PhonyExpression`
1569 const ast::PhonyExpression* Phony(const Source& source) {
1570 return create<ast::PhonyExpression>(source);
1571 }
James Priceebe97412022-04-07 13:42:45 +00001572
dan sinclair41e4d9a2022-05-01 14:40:55 +00001573 /// @returns a `ast::PhonyExpression`
1574 const ast::PhonyExpression* Phony() { return create<ast::PhonyExpression>(); }
James Priceebe97412022-04-07 13:42:45 +00001575
dan sinclair41e4d9a2022-05-01 14:40:55 +00001576 /// @param expr the expression to ignore
1577 /// @returns a `ast::AssignmentStatement` that assigns 'expr' to the phony
1578 /// (underscore) variable.
1579 template <typename EXPR>
1580 const ast::AssignmentStatement* Ignore(EXPR&& expr) {
1581 return create<ast::AssignmentStatement>(Phony(), Expr(expr));
1582 }
James Priceebe97412022-04-07 13:42:45 +00001583
dan sinclair41e4d9a2022-05-01 14:40:55 +00001584 /// @param lhs the left hand argument to the addition operation
1585 /// @param rhs the right hand argument to the addition operation
1586 /// @returns a `ast::BinaryExpression` summing the arguments `lhs` and `rhs`
1587 template <typename LHS, typename RHS>
1588 const ast::BinaryExpression* Add(LHS&& lhs, RHS&& rhs) {
1589 return create<ast::BinaryExpression>(ast::BinaryOp::kAdd, Expr(std::forward<LHS>(lhs)),
1590 Expr(std::forward<RHS>(rhs)));
1591 }
James Priceebe97412022-04-07 13:42:45 +00001592
dan sinclair41e4d9a2022-05-01 14:40:55 +00001593 /// @param lhs the left hand argument to the and operation
1594 /// @param rhs the right hand argument to the and operation
1595 /// @returns a `ast::BinaryExpression` bitwise anding `lhs` and `rhs`
1596 template <typename LHS, typename RHS>
1597 const ast::BinaryExpression* And(LHS&& lhs, RHS&& rhs) {
1598 return create<ast::BinaryExpression>(ast::BinaryOp::kAnd, Expr(std::forward<LHS>(lhs)),
1599 Expr(std::forward<RHS>(rhs)));
1600 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001601
dan sinclair41e4d9a2022-05-01 14:40:55 +00001602 /// @param lhs the left hand argument to the or operation
1603 /// @param rhs the right hand argument to the or operation
1604 /// @returns a `ast::BinaryExpression` bitwise or-ing `lhs` and `rhs`
1605 template <typename LHS, typename RHS>
1606 const ast::BinaryExpression* Or(LHS&& lhs, RHS&& rhs) {
1607 return create<ast::BinaryExpression>(ast::BinaryOp::kOr, Expr(std::forward<LHS>(lhs)),
1608 Expr(std::forward<RHS>(rhs)));
1609 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001610
dan sinclair41e4d9a2022-05-01 14:40:55 +00001611 /// @param lhs the left hand argument to the subtraction operation
1612 /// @param rhs the right hand argument to the subtraction operation
1613 /// @returns a `ast::BinaryExpression` subtracting `rhs` from `lhs`
1614 template <typename LHS, typename RHS>
1615 const ast::BinaryExpression* Sub(LHS&& lhs, RHS&& rhs) {
1616 return create<ast::BinaryExpression>(ast::BinaryOp::kSubtract, Expr(std::forward<LHS>(lhs)),
1617 Expr(std::forward<RHS>(rhs)));
1618 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001619
dan sinclair41e4d9a2022-05-01 14:40:55 +00001620 /// @param lhs the left hand argument to the multiplication operation
1621 /// @param rhs the right hand argument to the multiplication operation
1622 /// @returns a `ast::BinaryExpression` multiplying `rhs` from `lhs`
1623 template <typename LHS, typename RHS>
1624 const ast::BinaryExpression* Mul(LHS&& lhs, RHS&& rhs) {
1625 return create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, Expr(std::forward<LHS>(lhs)),
1626 Expr(std::forward<RHS>(rhs)));
1627 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001628
dan sinclair41e4d9a2022-05-01 14:40:55 +00001629 /// @param source the source information
1630 /// @param lhs the left hand argument to the multiplication operation
1631 /// @param rhs the right hand argument to the multiplication operation
1632 /// @returns a `ast::BinaryExpression` multiplying `rhs` from `lhs`
1633 template <typename LHS, typename RHS>
1634 const ast::BinaryExpression* Mul(const Source& source, LHS&& lhs, RHS&& rhs) {
1635 return create<ast::BinaryExpression>(source, ast::BinaryOp::kMultiply,
1636 Expr(std::forward<LHS>(lhs)),
1637 Expr(std::forward<RHS>(rhs)));
1638 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001639
dan sinclair41e4d9a2022-05-01 14:40:55 +00001640 /// @param lhs the left hand argument to the division operation
1641 /// @param rhs the right hand argument to the division operation
1642 /// @returns a `ast::BinaryExpression` dividing `lhs` by `rhs`
1643 template <typename LHS, typename RHS>
1644 const ast::BinaryExpression* Div(LHS&& lhs, RHS&& rhs) {
1645 return create<ast::BinaryExpression>(ast::BinaryOp::kDivide, Expr(std::forward<LHS>(lhs)),
1646 Expr(std::forward<RHS>(rhs)));
1647 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001648
dan sinclair41e4d9a2022-05-01 14:40:55 +00001649 /// @param lhs the left hand argument to the modulo operation
1650 /// @param rhs the right hand argument to the modulo operation
1651 /// @returns a `ast::BinaryExpression` applying modulo of `lhs` by `rhs`
1652 template <typename LHS, typename RHS>
1653 const ast::BinaryExpression* Mod(LHS&& lhs, RHS&& rhs) {
1654 return create<ast::BinaryExpression>(ast::BinaryOp::kModulo, Expr(std::forward<LHS>(lhs)),
1655 Expr(std::forward<RHS>(rhs)));
1656 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001657
dan sinclair41e4d9a2022-05-01 14:40:55 +00001658 /// @param lhs the left hand argument to the bit shift right operation
1659 /// @param rhs the right hand argument to the bit shift right operation
1660 /// @returns a `ast::BinaryExpression` bit shifting right `lhs` by `rhs`
1661 template <typename LHS, typename RHS>
1662 const ast::BinaryExpression* Shr(LHS&& lhs, RHS&& rhs) {
1663 return create<ast::BinaryExpression>(
1664 ast::BinaryOp::kShiftRight, Expr(std::forward<LHS>(lhs)), Expr(std::forward<RHS>(rhs)));
1665 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001666
dan sinclair41e4d9a2022-05-01 14:40:55 +00001667 /// @param lhs the left hand argument to the bit shift left operation
1668 /// @param rhs the right hand argument to the bit shift left operation
1669 /// @returns a `ast::BinaryExpression` bit shifting left `lhs` by `rhs`
1670 template <typename LHS, typename RHS>
1671 const ast::BinaryExpression* Shl(LHS&& lhs, RHS&& rhs) {
1672 return create<ast::BinaryExpression>(
1673 ast::BinaryOp::kShiftLeft, Expr(std::forward<LHS>(lhs)), Expr(std::forward<RHS>(rhs)));
1674 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001675
dan sinclair41e4d9a2022-05-01 14:40:55 +00001676 /// @param lhs the left hand argument to the xor operation
1677 /// @param rhs the right hand argument to the xor operation
1678 /// @returns a `ast::BinaryExpression` bitwise xor-ing `lhs` and `rhs`
1679 template <typename LHS, typename RHS>
1680 const ast::BinaryExpression* Xor(LHS&& lhs, RHS&& rhs) {
1681 return create<ast::BinaryExpression>(ast::BinaryOp::kXor, Expr(std::forward<LHS>(lhs)),
1682 Expr(std::forward<RHS>(rhs)));
1683 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001684
dan sinclair41e4d9a2022-05-01 14:40:55 +00001685 /// @param lhs the left hand argument to the logical and operation
1686 /// @param rhs the right hand argument to the logical and operation
1687 /// @returns a `ast::BinaryExpression` of `lhs` && `rhs`
1688 template <typename LHS, typename RHS>
1689 const ast::BinaryExpression* LogicalAnd(LHS&& lhs, RHS&& rhs) {
1690 return create<ast::BinaryExpression>(
1691 ast::BinaryOp::kLogicalAnd, Expr(std::forward<LHS>(lhs)), Expr(std::forward<RHS>(rhs)));
1692 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001693
dan sinclair41e4d9a2022-05-01 14:40:55 +00001694 /// @param lhs the left hand argument to the logical or operation
1695 /// @param rhs the right hand argument to the logical or operation
1696 /// @returns a `ast::BinaryExpression` of `lhs` || `rhs`
1697 template <typename LHS, typename RHS>
1698 const ast::BinaryExpression* LogicalOr(LHS&& lhs, RHS&& rhs) {
1699 return create<ast::BinaryExpression>(
1700 ast::BinaryOp::kLogicalOr, Expr(std::forward<LHS>(lhs)), Expr(std::forward<RHS>(rhs)));
1701 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001702
dan sinclair41e4d9a2022-05-01 14:40:55 +00001703 /// @param lhs the left hand argument to the greater than operation
1704 /// @param rhs the right hand argument to the greater than operation
1705 /// @returns a `ast::BinaryExpression` of `lhs` > `rhs`
1706 template <typename LHS, typename RHS>
1707 const ast::BinaryExpression* GreaterThan(LHS&& lhs, RHS&& rhs) {
1708 return create<ast::BinaryExpression>(ast::BinaryOp::kGreaterThan,
1709 Expr(std::forward<LHS>(lhs)),
1710 Expr(std::forward<RHS>(rhs)));
1711 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001712
dan sinclair41e4d9a2022-05-01 14:40:55 +00001713 /// @param lhs the left hand argument to the greater than or equal operation
1714 /// @param rhs the right hand argument to the greater than or equal operation
1715 /// @returns a `ast::BinaryExpression` of `lhs` >= `rhs`
1716 template <typename LHS, typename RHS>
1717 const ast::BinaryExpression* GreaterThanEqual(LHS&& lhs, RHS&& rhs) {
1718 return create<ast::BinaryExpression>(ast::BinaryOp::kGreaterThanEqual,
1719 Expr(std::forward<LHS>(lhs)),
1720 Expr(std::forward<RHS>(rhs)));
1721 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001722
dan sinclair41e4d9a2022-05-01 14:40:55 +00001723 /// @param lhs the left hand argument to the less than operation
1724 /// @param rhs the right hand argument to the less than operation
1725 /// @returns a `ast::BinaryExpression` of `lhs` < `rhs`
1726 template <typename LHS, typename RHS>
1727 const ast::BinaryExpression* LessThan(LHS&& lhs, RHS&& rhs) {
1728 return create<ast::BinaryExpression>(ast::BinaryOp::kLessThan, Expr(std::forward<LHS>(lhs)),
1729 Expr(std::forward<RHS>(rhs)));
1730 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001731
dan sinclair41e4d9a2022-05-01 14:40:55 +00001732 /// @param lhs the left hand argument to the less than or equal operation
1733 /// @param rhs the right hand argument to the less than or equal operation
1734 /// @returns a `ast::BinaryExpression` of `lhs` <= `rhs`
1735 template <typename LHS, typename RHS>
1736 const ast::BinaryExpression* LessThanEqual(LHS&& lhs, RHS&& rhs) {
1737 return create<ast::BinaryExpression>(ast::BinaryOp::kLessThanEqual,
1738 Expr(std::forward<LHS>(lhs)),
1739 Expr(std::forward<RHS>(rhs)));
1740 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001741
dan sinclair41e4d9a2022-05-01 14:40:55 +00001742 /// @param lhs the left hand argument to the equal expression
1743 /// @param rhs the right hand argument to the equal expression
1744 /// @returns a `ast::BinaryExpression` comparing `lhs` equal to `rhs`
1745 template <typename LHS, typename RHS>
1746 const ast::BinaryExpression* Equal(LHS&& lhs, RHS&& rhs) {
1747 return create<ast::BinaryExpression>(ast::BinaryOp::kEqual, Expr(std::forward<LHS>(lhs)),
1748 Expr(std::forward<RHS>(rhs)));
1749 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001750
dan sinclair41e4d9a2022-05-01 14:40:55 +00001751 /// @param lhs the left hand argument to the not-equal expression
1752 /// @param rhs the right hand argument to the not-equal expression
1753 /// @returns a `ast::BinaryExpression` comparing `lhs` equal to `rhs` for
1754 /// disequality
1755 template <typename LHS, typename RHS>
1756 const ast::BinaryExpression* NotEqual(LHS&& lhs, RHS&& rhs) {
1757 return create<ast::BinaryExpression>(ast::BinaryOp::kNotEqual, Expr(std::forward<LHS>(lhs)),
1758 Expr(std::forward<RHS>(rhs)));
1759 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001760
dan sinclair41e4d9a2022-05-01 14:40:55 +00001761 /// @param source the source information
1762 /// @param obj the object for the index accessor expression
1763 /// @param idx the index argument for the index accessor expression
1764 /// @returns a `ast::IndexAccessorExpression` that indexes `arr` with `idx`
1765 template <typename OBJ, typename IDX>
1766 const ast::IndexAccessorExpression* IndexAccessor(const Source& source, OBJ&& obj, IDX&& idx) {
1767 return create<ast::IndexAccessorExpression>(source, Expr(std::forward<OBJ>(obj)),
1768 Expr(std::forward<IDX>(idx)));
1769 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001770
dan sinclair41e4d9a2022-05-01 14:40:55 +00001771 /// @param obj the object for the index accessor expression
1772 /// @param idx the index argument for the index accessor expression
1773 /// @returns a `ast::IndexAccessorExpression` that indexes `arr` with `idx`
1774 template <typename OBJ, typename IDX>
1775 const ast::IndexAccessorExpression* IndexAccessor(OBJ&& obj, IDX&& idx) {
1776 return create<ast::IndexAccessorExpression>(Expr(std::forward<OBJ>(obj)),
1777 Expr(std::forward<IDX>(idx)));
1778 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001779
dan sinclair41e4d9a2022-05-01 14:40:55 +00001780 /// @param source the source information
1781 /// @param obj the object for the member accessor expression
1782 /// @param idx the index argument for the member accessor expression
1783 /// @returns a `ast::MemberAccessorExpression` that indexes `obj` with `idx`
1784 template <typename OBJ, typename IDX>
1785 const ast::MemberAccessorExpression* MemberAccessor(const Source& source,
1786 OBJ&& obj,
1787 IDX&& idx) {
1788 return create<ast::MemberAccessorExpression>(source, Expr(std::forward<OBJ>(obj)),
1789 Expr(std::forward<IDX>(idx)));
1790 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001791
dan sinclair41e4d9a2022-05-01 14:40:55 +00001792 /// @param obj the object for the member accessor expression
1793 /// @param idx the index argument for the member accessor expression
1794 /// @returns a `ast::MemberAccessorExpression` that indexes `obj` with `idx`
1795 template <typename OBJ, typename IDX>
1796 const ast::MemberAccessorExpression* MemberAccessor(OBJ&& obj, IDX&& idx) {
1797 return create<ast::MemberAccessorExpression>(Expr(std::forward<OBJ>(obj)),
1798 Expr(std::forward<IDX>(idx)));
1799 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001800
dan sinclair41e4d9a2022-05-01 14:40:55 +00001801 /// Creates a ast::StructMemberOffsetAttribute
1802 /// @param val the offset value
1803 /// @returns the offset attribute pointer
1804 const ast::StructMemberOffsetAttribute* MemberOffset(uint32_t val) {
1805 return create<ast::StructMemberOffsetAttribute>(source_, val);
1806 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001807
dan sinclair41e4d9a2022-05-01 14:40:55 +00001808 /// Creates a ast::StructMemberSizeAttribute
1809 /// @param source the source information
1810 /// @param val the size value
1811 /// @returns the size attribute pointer
1812 const ast::StructMemberSizeAttribute* MemberSize(const Source& source, uint32_t val) {
1813 return create<ast::StructMemberSizeAttribute>(source, val);
1814 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001815
dan sinclair41e4d9a2022-05-01 14:40:55 +00001816 /// Creates a ast::StructMemberSizeAttribute
1817 /// @param val the size value
1818 /// @returns the size attribute pointer
1819 const ast::StructMemberSizeAttribute* MemberSize(uint32_t val) {
1820 return create<ast::StructMemberSizeAttribute>(source_, val);
1821 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001822
dan sinclair41e4d9a2022-05-01 14:40:55 +00001823 /// Creates a ast::StructMemberAlignAttribute
1824 /// @param source the source information
1825 /// @param val the align value
1826 /// @returns the align attribute pointer
1827 const ast::StructMemberAlignAttribute* MemberAlign(const Source& source, uint32_t val) {
1828 return create<ast::StructMemberAlignAttribute>(source, val);
1829 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001830
dan sinclair41e4d9a2022-05-01 14:40:55 +00001831 /// Creates a ast::StructMemberAlignAttribute
1832 /// @param val the align value
1833 /// @returns the align attribute pointer
1834 const ast::StructMemberAlignAttribute* MemberAlign(uint32_t val) {
1835 return create<ast::StructMemberAlignAttribute>(source_, val);
1836 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001837
dan sinclair41e4d9a2022-05-01 14:40:55 +00001838 /// Creates the ast::GroupAttribute
1839 /// @param value group attribute index
1840 /// @returns the group attribute pointer
1841 const ast::GroupAttribute* Group(uint32_t value) { return create<ast::GroupAttribute>(value); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001842
dan sinclair41e4d9a2022-05-01 14:40:55 +00001843 /// Creates the ast::BindingAttribute
1844 /// @param value the binding index
1845 /// @returns the binding deocration pointer
1846 const ast::BindingAttribute* Binding(uint32_t value) {
1847 return create<ast::BindingAttribute>(value);
1848 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001849
dan sinclair41e4d9a2022-05-01 14:40:55 +00001850 /// Convenience function to create both a ast::GroupAttribute and
1851 /// ast::BindingAttribute
1852 /// @param group the group index
1853 /// @param binding the binding index
1854 /// @returns a attribute list with both the group and binding attributes
1855 ast::AttributeList GroupAndBinding(uint32_t group, uint32_t binding) {
1856 return {Group(group), Binding(binding)};
1857 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001858
dan sinclair41e4d9a2022-05-01 14:40:55 +00001859 /// Creates an ast::Function and registers it with the ast::Module.
1860 /// @param source the source information
1861 /// @param name the function name
1862 /// @param params the function parameters
1863 /// @param type the function return type
1864 /// @param body the function body
1865 /// @param attributes the optional function attributes
1866 /// @param return_type_attributes the optional function return type
1867 /// attributes
1868 /// @returns the function pointer
1869 template <typename NAME>
1870 const ast::Function* Func(const Source& source,
1871 NAME&& name,
1872 ast::VariableList params,
1873 const ast::Type* type,
1874 ast::StatementList body,
1875 ast::AttributeList attributes = {},
1876 ast::AttributeList return_type_attributes = {}) {
1877 auto* func = create<ast::Function>(source, Sym(std::forward<NAME>(name)), params, type,
1878 create<ast::BlockStatement>(body), attributes,
1879 return_type_attributes);
1880 AST().AddFunction(func);
1881 return func;
1882 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001883
dan sinclair41e4d9a2022-05-01 14:40:55 +00001884 /// Creates an ast::Function and registers it with the ast::Module.
1885 /// @param name the function name
1886 /// @param params the function parameters
1887 /// @param type the function return type
1888 /// @param body the function body
1889 /// @param attributes the optional function attributes
1890 /// @param return_type_attributes the optional function return type
1891 /// attributes
1892 /// @returns the function pointer
1893 template <typename NAME>
1894 const ast::Function* Func(NAME&& name,
1895 ast::VariableList params,
1896 const ast::Type* type,
1897 ast::StatementList body,
1898 ast::AttributeList attributes = {},
1899 ast::AttributeList return_type_attributes = {}) {
1900 auto* func = create<ast::Function>(Sym(std::forward<NAME>(name)), params, type,
1901 create<ast::BlockStatement>(body), attributes,
1902 return_type_attributes);
1903 AST().AddFunction(func);
1904 return func;
1905 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001906
dan sinclair41e4d9a2022-05-01 14:40:55 +00001907 /// Creates an ast::BreakStatement
1908 /// @param source the source information
1909 /// @returns the break statement pointer
1910 const ast::BreakStatement* Break(const Source& source) {
1911 return create<ast::BreakStatement>(source);
1912 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001913
dan sinclair41e4d9a2022-05-01 14:40:55 +00001914 /// Creates an ast::BreakStatement
1915 /// @returns the break statement pointer
1916 const ast::BreakStatement* Break() { return create<ast::BreakStatement>(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001917
dan sinclair41e4d9a2022-05-01 14:40:55 +00001918 /// Creates an ast::ContinueStatement
1919 /// @param source the source information
1920 /// @returns the continue statement pointer
1921 const ast::ContinueStatement* Continue(const Source& source) {
1922 return create<ast::ContinueStatement>(source);
1923 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001924
dan sinclair41e4d9a2022-05-01 14:40:55 +00001925 /// Creates an ast::ContinueStatement
1926 /// @returns the continue statement pointer
1927 const ast::ContinueStatement* Continue() { return create<ast::ContinueStatement>(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001928
dan sinclair41e4d9a2022-05-01 14:40:55 +00001929 /// Creates an ast::ReturnStatement with no return value
1930 /// @param source the source information
1931 /// @returns the return statement pointer
1932 const ast::ReturnStatement* Return(const Source& source) {
1933 return create<ast::ReturnStatement>(source);
1934 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001935
dan sinclair41e4d9a2022-05-01 14:40:55 +00001936 /// Creates an ast::ReturnStatement with no return value
1937 /// @returns the return statement pointer
1938 const ast::ReturnStatement* Return() { return create<ast::ReturnStatement>(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001939
dan sinclair41e4d9a2022-05-01 14:40:55 +00001940 /// Creates an ast::ReturnStatement with the given return value
1941 /// @param source the source information
1942 /// @param val the return value
1943 /// @returns the return statement pointer
1944 template <typename EXPR>
1945 const ast::ReturnStatement* Return(const Source& source, EXPR&& val) {
1946 return create<ast::ReturnStatement>(source, Expr(std::forward<EXPR>(val)));
1947 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001948
dan sinclair41e4d9a2022-05-01 14:40:55 +00001949 /// Creates an ast::ReturnStatement with the given return value
1950 /// @param val the return value
1951 /// @returns the return statement pointer
1952 template <typename EXPR, typename = DisableIfSource<EXPR>>
1953 const ast::ReturnStatement* Return(EXPR&& val) {
1954 return create<ast::ReturnStatement>(Expr(std::forward<EXPR>(val)));
1955 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001956
dan sinclair41e4d9a2022-05-01 14:40:55 +00001957 /// Creates an ast::DiscardStatement
1958 /// @param source the source information
1959 /// @returns the discard statement pointer
1960 const ast::DiscardStatement* Discard(const Source& source) {
1961 return create<ast::DiscardStatement>(source);
1962 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001963
dan sinclair41e4d9a2022-05-01 14:40:55 +00001964 /// Creates an ast::DiscardStatement
1965 /// @returns the discard statement pointer
1966 const ast::DiscardStatement* Discard() { return create<ast::DiscardStatement>(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001967
dan sinclair41e4d9a2022-05-01 14:40:55 +00001968 /// Creates a ast::Alias registering it with the AST().TypeDecls().
1969 /// @param source the source information
1970 /// @param name the alias name
1971 /// @param type the alias target type
1972 /// @returns the alias type
1973 template <typename NAME>
1974 const ast::Alias* Alias(const Source& source, NAME&& name, const ast::Type* type) {
1975 auto* out = ty.alias(source, std::forward<NAME>(name), type);
1976 AST().AddTypeDecl(out);
1977 return out;
1978 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001979
dan sinclair41e4d9a2022-05-01 14:40:55 +00001980 /// Creates a ast::Alias registering it with the AST().TypeDecls().
1981 /// @param name the alias name
1982 /// @param type the alias target type
1983 /// @returns the alias type
1984 template <typename NAME>
1985 const ast::Alias* Alias(NAME&& name, const ast::Type* type) {
1986 auto* out = ty.alias(std::forward<NAME>(name), type);
1987 AST().AddTypeDecl(out);
1988 return out;
1989 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001990
dan sinclair41e4d9a2022-05-01 14:40:55 +00001991 /// Creates a ast::Struct registering it with the AST().TypeDecls().
1992 /// @param source the source information
1993 /// @param name the struct name
1994 /// @param members the struct members
1995 /// @returns the struct type
1996 template <typename NAME>
1997 const ast::Struct* Structure(const Source& source, NAME&& name, ast::StructMemberList members) {
1998 auto sym = Sym(std::forward<NAME>(name));
1999 auto* type = create<ast::Struct>(source, sym, std::move(members), ast::AttributeList{});
2000 AST().AddTypeDecl(type);
2001 return type;
2002 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002003
dan sinclair41e4d9a2022-05-01 14:40:55 +00002004 /// Creates a ast::Struct registering it with the AST().TypeDecls().
2005 /// @param name the struct name
2006 /// @param members the struct members
2007 /// @returns the struct type
2008 template <typename NAME>
2009 const ast::Struct* Structure(NAME&& name, ast::StructMemberList members) {
2010 auto sym = Sym(std::forward<NAME>(name));
2011 auto* type = create<ast::Struct>(sym, std::move(members), ast::AttributeList{});
2012 AST().AddTypeDecl(type);
2013 return type;
2014 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002015
dan sinclair41e4d9a2022-05-01 14:40:55 +00002016 /// Creates a ast::StructMember
2017 /// @param source the source information
2018 /// @param name the struct member name
2019 /// @param type the struct member type
2020 /// @param attributes the optional struct member attributes
2021 /// @returns the struct member pointer
2022 template <typename NAME>
2023 const ast::StructMember* Member(const Source& source,
2024 NAME&& name,
2025 const ast::Type* type,
2026 ast::AttributeList attributes = {}) {
2027 return create<ast::StructMember>(source, Sym(std::forward<NAME>(name)), type,
2028 std::move(attributes));
2029 }
2030
2031 /// Creates a ast::StructMember
2032 /// @param name the struct member name
2033 /// @param type the struct member type
2034 /// @param attributes the optional struct member attributes
2035 /// @returns the struct member pointer
2036 template <typename NAME>
2037 const ast::StructMember* Member(NAME&& name,
2038 const ast::Type* type,
2039 ast::AttributeList attributes = {}) {
2040 return create<ast::StructMember>(source_, Sym(std::forward<NAME>(name)), type,
2041 std::move(attributes));
2042 }
2043
2044 /// Creates a ast::StructMember with the given byte offset
2045 /// @param offset the offset to use in the StructMemberOffsetattribute
2046 /// @param name the struct member name
2047 /// @param type the struct member type
2048 /// @returns the struct member pointer
2049 template <typename NAME>
2050 const ast::StructMember* Member(uint32_t offset, NAME&& name, const ast::Type* type) {
2051 return create<ast::StructMember>(source_, Sym(std::forward<NAME>(name)), type,
2052 ast::AttributeList{
2053 create<ast::StructMemberOffsetAttribute>(offset),
2054 });
2055 }
2056
2057 /// Creates a ast::BlockStatement with input statements
2058 /// @param source the source information for the block
2059 /// @param statements statements of block
2060 /// @returns the block statement pointer
2061 template <typename... Statements>
2062 const ast::BlockStatement* Block(const Source& source, Statements&&... statements) {
2063 return create<ast::BlockStatement>(
2064 source, ast::StatementList{std::forward<Statements>(statements)...});
2065 }
2066
2067 /// Creates a ast::BlockStatement with input statements
2068 /// @param statements statements of block
2069 /// @returns the block statement pointer
2070 template <typename... STATEMENTS, typename = DisableIfSource<STATEMENTS...>>
2071 const ast::BlockStatement* Block(STATEMENTS&&... statements) {
2072 return create<ast::BlockStatement>(
2073 ast::StatementList{std::forward<STATEMENTS>(statements)...});
2074 }
2075
James Price8aff0ed2022-05-02 14:53:36 +00002076 /// A wrapper type for the Else statement used to create If statements.
2077 struct ElseStmt {
2078 /// Default constructor - no else statement.
2079 ElseStmt() : stmt(nullptr) {}
2080 /// Constructor
2081 /// @param s The else statement
2082 explicit ElseStmt(const ast::Statement* s) : stmt(s) {}
2083 /// The else statement, or nullptr.
2084 const ast::Statement* stmt;
2085 };
2086
dan sinclair41e4d9a2022-05-01 14:40:55 +00002087 /// Creates a ast::IfStatement with input condition, body, and optional
2088 /// else statement
2089 /// @param source the source information for the if statement
2090 /// @param condition the if statement condition expression
2091 /// @param body the if statement body
2092 /// @param else_stmt optional else statement
2093 /// @returns the if statement pointer
2094 template <typename CONDITION>
2095 const ast::IfStatement* If(const Source& source,
2096 CONDITION&& condition,
2097 const ast::BlockStatement* body,
James Price8aff0ed2022-05-02 14:53:36 +00002098 const ElseStmt else_stmt = ElseStmt()) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00002099 return create<ast::IfStatement>(source, Expr(std::forward<CONDITION>(condition)), body,
James Price8aff0ed2022-05-02 14:53:36 +00002100 else_stmt.stmt);
dan sinclair41e4d9a2022-05-01 14:40:55 +00002101 }
2102
2103 /// Creates a ast::IfStatement with input condition, body, and optional
2104 /// else statement
2105 /// @param condition the if statement condition expression
2106 /// @param body the if statement body
2107 /// @param else_stmt optional else statement
2108 /// @returns the if statement pointer
2109 template <typename CONDITION>
2110 const ast::IfStatement* If(CONDITION&& condition,
2111 const ast::BlockStatement* body,
James Price8aff0ed2022-05-02 14:53:36 +00002112 const ElseStmt else_stmt = ElseStmt()) {
2113 return create<ast::IfStatement>(Expr(std::forward<CONDITION>(condition)), body,
2114 else_stmt.stmt);
dan sinclair41e4d9a2022-05-01 14:40:55 +00002115 }
2116
James Price8aff0ed2022-05-02 14:53:36 +00002117 /// Creates an Else object.
2118 /// @param stmt else statement
2119 /// @returns the Else object
2120 ElseStmt Else(const ast::Statement* stmt) { return ElseStmt(stmt); }
2121
dan sinclair41e4d9a2022-05-01 14:40:55 +00002122 /// Creates a ast::AssignmentStatement with input lhs and rhs expressions
2123 /// @param source the source information
2124 /// @param lhs the left hand side expression initializer
2125 /// @param rhs the right hand side expression initializer
2126 /// @returns the assignment statement pointer
2127 template <typename LhsExpressionInit, typename RhsExpressionInit>
2128 const ast::AssignmentStatement* Assign(const Source& source,
2129 LhsExpressionInit&& lhs,
2130 RhsExpressionInit&& rhs) {
2131 return create<ast::AssignmentStatement>(source, Expr(std::forward<LhsExpressionInit>(lhs)),
2132 Expr(std::forward<RhsExpressionInit>(rhs)));
2133 }
2134
2135 /// Creates a ast::AssignmentStatement with input lhs and rhs expressions
2136 /// @param lhs the left hand side expression initializer
2137 /// @param rhs the right hand side expression initializer
2138 /// @returns the assignment statement pointer
2139 template <typename LhsExpressionInit, typename RhsExpressionInit>
2140 const ast::AssignmentStatement* Assign(LhsExpressionInit&& lhs, RhsExpressionInit&& rhs) {
2141 return create<ast::AssignmentStatement>(Expr(std::forward<LhsExpressionInit>(lhs)),
2142 Expr(std::forward<RhsExpressionInit>(rhs)));
2143 }
2144
2145 /// Creates a ast::CompoundAssignmentStatement with input lhs and rhs
2146 /// expressions, and a binary operator.
2147 /// @param source the source information
2148 /// @param lhs the left hand side expression initializer
2149 /// @param rhs the right hand side expression initializer
2150 /// @param op the binary operator
2151 /// @returns the compound assignment statement pointer
2152 template <typename LhsExpressionInit, typename RhsExpressionInit>
2153 const ast::CompoundAssignmentStatement* CompoundAssign(const Source& source,
2154 LhsExpressionInit&& lhs,
2155 RhsExpressionInit&& rhs,
2156 ast::BinaryOp op) {
2157 return create<ast::CompoundAssignmentStatement>(
2158 source, Expr(std::forward<LhsExpressionInit>(lhs)),
2159 Expr(std::forward<RhsExpressionInit>(rhs)), op);
2160 }
2161
2162 /// Creates a ast::CompoundAssignmentStatement with input lhs and rhs
2163 /// expressions, and a binary operator.
2164 /// @param lhs the left hand side expression initializer
2165 /// @param rhs the right hand side expression initializer
2166 /// @param op the binary operator
2167 /// @returns the compound assignment statement pointer
2168 template <typename LhsExpressionInit, typename RhsExpressionInit>
2169 const ast::CompoundAssignmentStatement* CompoundAssign(LhsExpressionInit&& lhs,
2170 RhsExpressionInit&& rhs,
2171 ast::BinaryOp op) {
2172 return create<ast::CompoundAssignmentStatement>(Expr(std::forward<LhsExpressionInit>(lhs)),
2173 Expr(std::forward<RhsExpressionInit>(rhs)),
2174 op);
2175 }
2176
2177 /// Creates an ast::IncrementDecrementStatement with input lhs.
2178 /// @param source the source information
2179 /// @param lhs the left hand side expression initializer
2180 /// @returns the increment decrement statement pointer
2181 template <typename LhsExpressionInit>
2182 const ast::IncrementDecrementStatement* Increment(const Source& source,
2183 LhsExpressionInit&& lhs) {
2184 return create<ast::IncrementDecrementStatement>(
2185 source, Expr(std::forward<LhsExpressionInit>(lhs)), true);
2186 }
2187
2188 /// Creates a ast::IncrementDecrementStatement with input lhs.
2189 /// @param lhs the left hand side expression initializer
2190 /// @returns the increment decrement statement pointer
2191 template <typename LhsExpressionInit>
2192 const ast::IncrementDecrementStatement* Increment(LhsExpressionInit&& lhs) {
2193 return create<ast::IncrementDecrementStatement>(Expr(std::forward<LhsExpressionInit>(lhs)),
2194 true);
2195 }
2196
2197 /// Creates an ast::IncrementDecrementStatement with input lhs.
2198 /// @param source the source information
2199 /// @param lhs the left hand side expression initializer
2200 /// @returns the increment decrement statement pointer
2201 template <typename LhsExpressionInit>
2202 const ast::IncrementDecrementStatement* Decrement(const Source& source,
2203 LhsExpressionInit&& lhs) {
2204 return create<ast::IncrementDecrementStatement>(
2205 source, Expr(std::forward<LhsExpressionInit>(lhs)), false);
2206 }
2207
2208 /// Creates a ast::IncrementDecrementStatement with input lhs.
2209 /// @param lhs the left hand side expression initializer
2210 /// @returns the increment decrement statement pointer
2211 template <typename LhsExpressionInit>
2212 const ast::IncrementDecrementStatement* Decrement(LhsExpressionInit&& lhs) {
2213 return create<ast::IncrementDecrementStatement>(Expr(std::forward<LhsExpressionInit>(lhs)),
2214 false);
2215 }
2216
2217 /// Creates a ast::LoopStatement with input body and optional continuing
2218 /// @param source the source information
2219 /// @param body the loop body
2220 /// @param continuing the optional continuing block
2221 /// @returns the loop statement pointer
2222 const ast::LoopStatement* Loop(const Source& source,
2223 const ast::BlockStatement* body,
2224 const ast::BlockStatement* continuing = nullptr) {
2225 return create<ast::LoopStatement>(source, body, continuing);
2226 }
2227
2228 /// Creates a ast::LoopStatement with input body and optional continuing
2229 /// @param body the loop body
2230 /// @param continuing the optional continuing block
2231 /// @returns the loop statement pointer
2232 const ast::LoopStatement* Loop(const ast::BlockStatement* body,
2233 const ast::BlockStatement* continuing = nullptr) {
2234 return create<ast::LoopStatement>(body, continuing);
2235 }
2236
2237 /// Creates a ast::ForLoopStatement with input body and optional initializer,
2238 /// condition and continuing.
2239 /// @param source the source information
2240 /// @param init the optional loop initializer
2241 /// @param cond the optional loop condition
2242 /// @param cont the optional loop continuing
2243 /// @param body the loop body
2244 /// @returns the for loop statement pointer
2245 template <typename COND>
2246 const ast::ForLoopStatement* For(const Source& source,
2247 const ast::Statement* init,
2248 COND&& cond,
2249 const ast::Statement* cont,
2250 const ast::BlockStatement* body) {
2251 return create<ast::ForLoopStatement>(source, init, Expr(std::forward<COND>(cond)), cont,
2252 body);
2253 }
2254
2255 /// Creates a ast::ForLoopStatement with input body and optional initializer,
2256 /// condition and continuing.
2257 /// @param init the optional loop initializer
2258 /// @param cond the optional loop condition
2259 /// @param cont the optional loop continuing
2260 /// @param body the loop body
2261 /// @returns the for loop statement pointer
2262 template <typename COND>
2263 const ast::ForLoopStatement* For(const ast::Statement* init,
2264 COND&& cond,
2265 const ast::Statement* cont,
2266 const ast::BlockStatement* body) {
2267 return create<ast::ForLoopStatement>(init, Expr(std::forward<COND>(cond)), cont, body);
2268 }
2269
2270 /// Creates a ast::VariableDeclStatement for the input variable
2271 /// @param source the source information
2272 /// @param var the variable to wrap in a decl statement
2273 /// @returns the variable decl statement pointer
2274 const ast::VariableDeclStatement* Decl(const Source& source, const ast::Variable* var) {
2275 return create<ast::VariableDeclStatement>(source, var);
2276 }
2277
2278 /// Creates a ast::VariableDeclStatement for the input variable
2279 /// @param var the variable to wrap in a decl statement
2280 /// @returns the variable decl statement pointer
2281 const ast::VariableDeclStatement* Decl(const ast::Variable* var) {
2282 return create<ast::VariableDeclStatement>(var);
2283 }
2284
2285 /// Creates a ast::SwitchStatement with input expression and cases
2286 /// @param source the source information
2287 /// @param condition the condition expression initializer
2288 /// @param cases case statements
2289 /// @returns the switch statement pointer
2290 template <typename ExpressionInit, typename... Cases>
2291 const ast::SwitchStatement* Switch(const Source& source,
2292 ExpressionInit&& condition,
2293 Cases&&... cases) {
2294 return create<ast::SwitchStatement>(source, Expr(std::forward<ExpressionInit>(condition)),
2295 ast::CaseStatementList{std::forward<Cases>(cases)...});
2296 }
2297
2298 /// Creates a ast::SwitchStatement with input expression and cases
2299 /// @param condition the condition expression initializer
2300 /// @param cases case statements
2301 /// @returns the switch statement pointer
2302 template <typename ExpressionInit,
2303 typename... Cases,
2304 typename = DisableIfSource<ExpressionInit>>
2305 const ast::SwitchStatement* Switch(ExpressionInit&& condition, Cases&&... cases) {
2306 return create<ast::SwitchStatement>(Expr(std::forward<ExpressionInit>(condition)),
2307 ast::CaseStatementList{std::forward<Cases>(cases)...});
2308 }
2309
2310 /// Creates a ast::CaseStatement with input list of selectors, and body
2311 /// @param source the source information
2312 /// @param selectors list of selectors
2313 /// @param body the case body
2314 /// @returns the case statement pointer
2315 const ast::CaseStatement* Case(const Source& source,
2316 ast::CaseSelectorList selectors,
2317 const ast::BlockStatement* body = nullptr) {
2318 return create<ast::CaseStatement>(source, std::move(selectors), body ? body : Block());
2319 }
2320
2321 /// Creates a ast::CaseStatement with input list of selectors, and body
2322 /// @param selectors list of selectors
2323 /// @param body the case body
2324 /// @returns the case statement pointer
2325 const ast::CaseStatement* Case(ast::CaseSelectorList selectors,
2326 const ast::BlockStatement* body = nullptr) {
2327 return create<ast::CaseStatement>(std::move(selectors), body ? body : Block());
2328 }
2329
2330 /// Convenient overload that takes a single selector
2331 /// @param selector a single case selector
2332 /// @param body the case body
2333 /// @returns the case statement pointer
2334 const ast::CaseStatement* Case(const ast::IntLiteralExpression* selector,
2335 const ast::BlockStatement* body = nullptr) {
2336 return Case(ast::CaseSelectorList{selector}, body);
2337 }
2338
2339 /// Convenience function that creates a 'default' ast::CaseStatement
2340 /// @param source the source information
2341 /// @param body the case body
2342 /// @returns the case statement pointer
2343 const ast::CaseStatement* DefaultCase(const Source& source,
2344 const ast::BlockStatement* body = nullptr) {
2345 return Case(source, ast::CaseSelectorList{}, body);
2346 }
2347
2348 /// Convenience function that creates a 'default' ast::CaseStatement
2349 /// @param body the case body
2350 /// @returns the case statement pointer
2351 const ast::CaseStatement* DefaultCase(const ast::BlockStatement* body = nullptr) {
2352 return Case(ast::CaseSelectorList{}, body);
2353 }
2354
2355 /// Creates an ast::FallthroughStatement
2356 /// @param source the source information
2357 /// @returns the fallthrough statement pointer
2358 const ast::FallthroughStatement* Fallthrough(const Source& source) {
2359 return create<ast::FallthroughStatement>(source);
2360 }
2361
2362 /// Creates an ast::FallthroughStatement
2363 /// @returns the fallthrough statement pointer
2364 const ast::FallthroughStatement* Fallthrough() { return create<ast::FallthroughStatement>(); }
2365
2366 /// Creates an ast::BuiltinAttribute
2367 /// @param source the source information
2368 /// @param builtin the builtin value
2369 /// @returns the builtin attribute pointer
2370 const ast::BuiltinAttribute* Builtin(const Source& source, ast::Builtin builtin) {
2371 return create<ast::BuiltinAttribute>(source, builtin);
2372 }
2373
2374 /// Creates an ast::BuiltinAttribute
2375 /// @param builtin the builtin value
2376 /// @returns the builtin attribute pointer
2377 const ast::BuiltinAttribute* Builtin(ast::Builtin builtin) {
2378 return create<ast::BuiltinAttribute>(source_, builtin);
2379 }
2380
2381 /// Creates an ast::InterpolateAttribute
2382 /// @param source the source information
2383 /// @param type the interpolation type
2384 /// @param sampling the interpolation sampling
2385 /// @returns the interpolate attribute pointer
2386 const ast::InterpolateAttribute* Interpolate(
2387 const Source& source,
2388 ast::InterpolationType type,
2389 ast::InterpolationSampling sampling = ast::InterpolationSampling::kNone) {
2390 return create<ast::InterpolateAttribute>(source, type, sampling);
2391 }
2392
2393 /// Creates an ast::InterpolateAttribute
2394 /// @param type the interpolation type
2395 /// @param sampling the interpolation sampling
2396 /// @returns the interpolate attribute pointer
2397 const ast::InterpolateAttribute* Interpolate(
2398 ast::InterpolationType type,
2399 ast::InterpolationSampling sampling = ast::InterpolationSampling::kNone) {
2400 return create<ast::InterpolateAttribute>(source_, type, sampling);
2401 }
2402
2403 /// Creates an ast::InterpolateAttribute using flat interpolation
2404 /// @param source the source information
2405 /// @returns the interpolate attribute pointer
2406 const ast::InterpolateAttribute* Flat(const Source& source) {
2407 return Interpolate(source, ast::InterpolationType::kFlat);
2408 }
2409
2410 /// Creates an ast::InterpolateAttribute using flat interpolation
2411 /// @returns the interpolate attribute pointer
2412 const ast::InterpolateAttribute* Flat() { return Interpolate(ast::InterpolationType::kFlat); }
2413
2414 /// Creates an ast::InvariantAttribute
2415 /// @param source the source information
2416 /// @returns the invariant attribute pointer
2417 const ast::InvariantAttribute* Invariant(const Source& source) {
2418 return create<ast::InvariantAttribute>(source);
2419 }
2420
2421 /// Creates an ast::InvariantAttribute
2422 /// @returns the invariant attribute pointer
2423 const ast::InvariantAttribute* Invariant() { return create<ast::InvariantAttribute>(source_); }
2424
2425 /// Creates an ast::LocationAttribute
2426 /// @param source the source information
2427 /// @param location the location value
2428 /// @returns the location attribute pointer
2429 const ast::LocationAttribute* Location(const Source& source, uint32_t location) {
2430 return create<ast::LocationAttribute>(source, location);
2431 }
2432
2433 /// Creates an ast::LocationAttribute
2434 /// @param location the location value
2435 /// @returns the location attribute pointer
2436 const ast::LocationAttribute* Location(uint32_t location) {
2437 return create<ast::LocationAttribute>(source_, location);
2438 }
2439
2440 /// Creates an ast::IdAttribute
2441 /// @param source the source information
2442 /// @param id the id value
2443 /// @returns the override attribute pointer
2444 const ast::IdAttribute* Id(const Source& source, uint32_t id) {
2445 return create<ast::IdAttribute>(source, id);
2446 }
2447
2448 /// Creates an ast::IdAttribute with a constant ID
2449 /// @param id the optional id value
2450 /// @returns the override attribute pointer
2451 const ast::IdAttribute* Id(uint32_t id) { return Id(source_, id); }
2452
2453 /// Creates an ast::StageAttribute
2454 /// @param source the source information
2455 /// @param stage the pipeline stage
2456 /// @returns the stage attribute pointer
2457 const ast::StageAttribute* Stage(const Source& source, ast::PipelineStage stage) {
2458 return create<ast::StageAttribute>(source, stage);
2459 }
2460
2461 /// Creates an ast::StageAttribute
2462 /// @param stage the pipeline stage
2463 /// @returns the stage attribute pointer
2464 const ast::StageAttribute* Stage(ast::PipelineStage stage) {
2465 return create<ast::StageAttribute>(source_, stage);
2466 }
2467
2468 /// Creates an ast::WorkgroupAttribute
2469 /// @param x the x dimension expression
2470 /// @returns the workgroup attribute pointer
2471 template <typename EXPR_X>
2472 const ast::WorkgroupAttribute* WorkgroupSize(EXPR_X&& x) {
2473 return WorkgroupSize(std::forward<EXPR_X>(x), nullptr, nullptr);
2474 }
2475
2476 /// Creates an ast::WorkgroupAttribute
2477 /// @param x the x dimension expression
2478 /// @param y the y dimension expression
2479 /// @returns the workgroup attribute pointer
2480 template <typename EXPR_X, typename EXPR_Y>
2481 const ast::WorkgroupAttribute* WorkgroupSize(EXPR_X&& x, EXPR_Y&& y) {
2482 return WorkgroupSize(std::forward<EXPR_X>(x), std::forward<EXPR_Y>(y), nullptr);
2483 }
2484
2485 /// Creates an ast::WorkgroupAttribute
2486 /// @param source the source information
2487 /// @param x the x dimension expression
2488 /// @param y the y dimension expression
2489 /// @param z the z dimension expression
2490 /// @returns the workgroup attribute pointer
2491 template <typename EXPR_X, typename EXPR_Y, typename EXPR_Z>
2492 const ast::WorkgroupAttribute* WorkgroupSize(const Source& source,
2493 EXPR_X&& x,
2494 EXPR_Y&& y,
2495 EXPR_Z&& z) {
2496 return create<ast::WorkgroupAttribute>(source, Expr(std::forward<EXPR_X>(x)),
2497 Expr(std::forward<EXPR_Y>(y)),
2498 Expr(std::forward<EXPR_Z>(z)));
2499 }
2500
2501 /// Creates an ast::WorkgroupAttribute
2502 /// @param x the x dimension expression
2503 /// @param y the y dimension expression
2504 /// @param z the z dimension expression
2505 /// @returns the workgroup attribute pointer
2506 template <typename EXPR_X, typename EXPR_Y, typename EXPR_Z>
2507 const ast::WorkgroupAttribute* WorkgroupSize(EXPR_X&& x, EXPR_Y&& y, EXPR_Z&& z) {
2508 return create<ast::WorkgroupAttribute>(source_, Expr(std::forward<EXPR_X>(x)),
2509 Expr(std::forward<EXPR_Y>(y)),
2510 Expr(std::forward<EXPR_Z>(z)));
2511 }
2512
2513 /// Creates an ast::DisableValidationAttribute
2514 /// @param validation the validation to disable
2515 /// @returns the disable validation attribute pointer
2516 const ast::DisableValidationAttribute* Disable(ast::DisabledValidation validation) {
2517 return ASTNodes().Create<ast::DisableValidationAttribute>(ID(), validation);
2518 }
2519
2520 /// Sets the current builder source to `src`
2521 /// @param src the Source used for future create() calls
2522 void SetSource(const Source& src) {
2523 AssertNotMoved();
2524 source_ = src;
2525 }
2526
2527 /// Sets the current builder source to `loc`
2528 /// @param loc the Source used for future create() calls
2529 void SetSource(const Source::Location& loc) {
2530 AssertNotMoved();
2531 source_ = Source(loc);
2532 }
2533
2534 /// Helper for returning the resolved semantic type of the expression `expr`.
2535 /// @note As the Resolver is run when the Program is built, this will only be
2536 /// useful for the Resolver itself and tests that use their own Resolver.
2537 /// @param expr the AST expression
2538 /// @return the resolved semantic type for the expression, or nullptr if the
2539 /// expression has no resolved type.
2540 const sem::Type* TypeOf(const ast::Expression* expr) const;
2541
2542 /// Helper for returning the resolved semantic type of the variable `var`.
2543 /// @note As the Resolver is run when the Program is built, this will only be
2544 /// useful for the Resolver itself and tests that use their own Resolver.
2545 /// @param var the AST variable
2546 /// @return the resolved semantic type for the variable, or nullptr if the
2547 /// variable has no resolved type.
2548 const sem::Type* TypeOf(const ast::Variable* var) const;
2549
2550 /// Helper for returning the resolved semantic type of the AST type `type`.
2551 /// @note As the Resolver is run when the Program is built, this will only be
2552 /// useful for the Resolver itself and tests that use their own Resolver.
2553 /// @param type the AST type
2554 /// @return the resolved semantic type for the type, or nullptr if the type
2555 /// has no resolved type.
2556 const sem::Type* TypeOf(const ast::Type* type) const;
2557
2558 /// Helper for returning the resolved semantic type of the AST type
2559 /// declaration `type_decl`.
2560 /// @note As the Resolver is run when the Program is built, this will only be
2561 /// useful for the Resolver itself and tests that use their own Resolver.
2562 /// @param type_decl the AST type declaration
2563 /// @return the resolved semantic type for the type declaration, or nullptr if
2564 /// the type declaration has no resolved type.
2565 const sem::Type* TypeOf(const ast::TypeDecl* type_decl) const;
2566
2567 /// Wraps the ast::Expression in a statement. This is used by tests that
2568 /// construct a partial AST and require the Resolver to reach these
2569 /// nodes.
2570 /// @param expr the ast::Expression to be wrapped by an ast::Statement
2571 /// @return the ast::Statement that wraps the ast::Expression
2572 const ast::Statement* WrapInStatement(const ast::Expression* expr);
2573 /// Wraps the ast::Variable in a ast::VariableDeclStatement. This is used by
2574 /// tests that construct a partial AST and require the Resolver to reach
2575 /// these nodes.
2576 /// @param v the ast::Variable to be wrapped by an ast::VariableDeclStatement
2577 /// @return the ast::VariableDeclStatement that wraps the ast::Variable
2578 const ast::VariableDeclStatement* WrapInStatement(const ast::Variable* v);
2579 /// Returns the statement argument. Used as a passthrough-overload by
2580 /// WrapInFunction().
2581 /// @param stmt the ast::Statement
2582 /// @return `stmt`
2583 const ast::Statement* WrapInStatement(const ast::Statement* stmt);
2584 /// Wraps the list of arguments in a simple function so that each is reachable
2585 /// by the Resolver.
2586 /// @param args a mix of ast::Expression, ast::Statement, ast::Variables.
2587 /// @returns the function
2588 template <typename... ARGS>
2589 const ast::Function* WrapInFunction(ARGS&&... args) {
2590 ast::StatementList stmts{WrapInStatement(std::forward<ARGS>(args))...};
2591 return WrapInFunction(std::move(stmts));
2592 }
2593 /// @param stmts a list of ast::Statement that will be wrapped by a function,
2594 /// so that each statement is reachable by the Resolver.
2595 /// @returns the function
2596 const ast::Function* WrapInFunction(ast::StatementList stmts);
2597
2598 /// The builder types
2599 TypesBuilder const ty{this};
2600
2601 protected:
2602 /// Asserts that the builder has not been moved.
2603 void AssertNotMoved() const;
2604
2605 private:
2606 ProgramID id_;
2607 sem::Manager types_;
2608 ASTNodeAllocator ast_nodes_;
2609 SemNodeAllocator sem_nodes_;
2610 ast::Module* ast_;
2611 sem::Info sem_;
2612 SymbolTable symbols_{id_};
2613 diag::List diagnostics_;
2614
2615 /// The source to use when creating AST nodes without providing a Source as
2616 /// the first argument.
2617 Source source_;
2618
2619 /// Set by SetResolveOnBuild(). If set, the Resolver will be run on the
2620 /// program when built.
2621 bool resolve_on_build_ = true;
2622
2623 /// Set by MarkAsMoved(). Once set, no methods may be called on this builder.
2624 bool moved_ = false;
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002625};
2626
2627//! @cond Doxygen_Suppress
2628// Various template specializations for ProgramBuilder::TypesBuilder::CToAST.
2629template <>
Ben Clayton0ce9ab02022-05-05 20:23:40 +00002630struct ProgramBuilder::TypesBuilder::CToAST<i32> {
dan sinclair41e4d9a2022-05-01 14:40:55 +00002631 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->i32(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002632};
2633template <>
Ben Clayton0ce9ab02022-05-05 20:23:40 +00002634struct ProgramBuilder::TypesBuilder::CToAST<u32> {
dan sinclair41e4d9a2022-05-01 14:40:55 +00002635 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->u32(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002636};
2637template <>
Ben Clayton0ce9ab02022-05-05 20:23:40 +00002638struct ProgramBuilder::TypesBuilder::CToAST<f32> {
dan sinclair41e4d9a2022-05-01 14:40:55 +00002639 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->f32(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002640};
2641template <>
2642struct ProgramBuilder::TypesBuilder::CToAST<bool> {
dan sinclair41e4d9a2022-05-01 14:40:55 +00002643 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->bool_(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002644};
2645template <>
2646struct ProgramBuilder::TypesBuilder::CToAST<void> {
dan sinclair41e4d9a2022-05-01 14:40:55 +00002647 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->void_(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002648};
2649//! @endcond
2650
2651/// @param builder the ProgramBuilder
2652/// @returns the ProgramID of the ProgramBuilder
2653inline ProgramID ProgramIDOf(const ProgramBuilder* builder) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00002654 return builder->ID();
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002655}
2656
2657} // namespace tint
2658
2659#endif // SRC_TINT_PROGRAM_BUILDER_H_