blob: 7e3d602021acd05e4d057500873054e74528ad98 [file] [log] [blame]
Ben Claytona6b9a8e2021-01-26 16:57:10 +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_PROGRAM_BUILDER_H_
16#define SRC_PROGRAM_BUILDER_H_
17
18#include <string>
19#include <utility>
20
21#include "src/ast/array_accessor_expression.h"
22#include "src/ast/binary_expression.h"
23#include "src/ast/bool_literal.h"
24#include "src/ast/call_expression.h"
25#include "src/ast/expression.h"
26#include "src/ast/float_literal.h"
27#include "src/ast/identifier_expression.h"
28#include "src/ast/member_accessor_expression.h"
29#include "src/ast/module.h"
30#include "src/ast/scalar_constructor_expression.h"
31#include "src/ast/sint_literal.h"
32#include "src/ast/struct.h"
33#include "src/ast/struct_member.h"
34#include "src/ast/struct_member_offset_decoration.h"
35#include "src/ast/type_constructor_expression.h"
36#include "src/ast/uint_literal.h"
37#include "src/ast/variable.h"
38#include "src/program.h"
39#include "src/symbol_table.h"
40#include "src/type/alias_type.h"
41#include "src/type/array_type.h"
42#include "src/type/bool_type.h"
43#include "src/type/f32_type.h"
44#include "src/type/i32_type.h"
45#include "src/type/matrix_type.h"
46#include "src/type/pointer_type.h"
47#include "src/type/struct_type.h"
48#include "src/type/type_manager.h"
49#include "src/type/u32_type.h"
50#include "src/type/vector_type.h"
51#include "src/type/void_type.h"
52
53namespace tint {
54
55class CloneContext;
56
57/// ProgramBuilder is a mutable builder for a Program.
58/// To construct a Program, populate the builder and then `std::move` it to a
59/// Program.
60class ProgramBuilder {
61 public:
62 /// ASTNodes is an alias to BlockAllocator<ast::Node>
63 using ASTNodes = BlockAllocator<ast::Node>;
64
65 /// `i32` is a type alias to `int`.
66 /// Useful for passing to template methods such as `vec2<i32>()` to imitate
67 /// WGSL syntax.
68 /// Note: this is intentionally not aliased to uint32_t as we want integer
69 /// literals passed to the builder to match WGSL's integer literal types.
70 using i32 = decltype(1);
71 /// `u32` is a type alias to `unsigned int`.
72 /// Useful for passing to template methods such as `vec2<u32>()` to imitate
73 /// WGSL syntax.
74 /// Note: this is intentionally not aliased to uint32_t as we want integer
75 /// literals passed to the builder to match WGSL's integer literal types.
76 using u32 = decltype(1u);
77 /// `f32` is a type alias to `float`
78 /// Useful for passing to template methods such as `vec2<f32>()` to imitate
79 /// WGSL syntax.
80 using f32 = float;
81
82 /// Constructor
83 ProgramBuilder();
84
85 /// Move constructor
86 /// @param rhs the builder to move
87 ProgramBuilder(ProgramBuilder&& rhs);
88
89 /// Destructor
90 virtual ~ProgramBuilder();
91
92 /// Move assignment operator
93 /// @param rhs the builder to move
94 /// @return this builder
95 ProgramBuilder& operator=(ProgramBuilder&& rhs);
96
97 /// @returns a reference to the program's types
98 type::Manager& Types() {
99 AssertNotMoved();
100 return types_;
101 }
102
103 /// @returns a reference to the program's AST nodes storage
104 ASTNodes& Nodes() {
105 AssertNotMoved();
106 return nodes_;
107 }
108
109 /// @returns a reference to the program's AST root Module
110 ast::Module& AST() {
111 AssertNotMoved();
112 return *ast_;
113 }
114
115 /// @returns a reference to the program's SymbolTable
116 SymbolTable& Symbols() {
117 AssertNotMoved();
118 return symbols_;
119 }
120
121 /// @returns true if the program not missing information
122 bool IsValid() const;
123
124 /// creates a new ast::Node owned by the Module. When the Module is
125 /// destructed, the ast::Node will also be destructed.
126 /// @param source the Source of the node
127 /// @param args the arguments to pass to the type constructor
128 /// @returns the node pointer
129 template <typename T, typename... ARGS>
130 traits::EnableIfIsType<T, ast::Node>* create(const Source& source,
131 ARGS&&... args) {
132 AssertNotMoved();
133 return nodes_.Create<T>(source, std::forward<ARGS>(args)...);
134 }
135
136 /// creates a new ast::Node owned by the Module, injecting the current Source
137 /// as set by the last call to SetSource() as the only argument to the
138 /// constructor.
139 /// When the Module is destructed, the ast::Node will also be destructed.
140 /// @returns the node pointer
141 template <typename T>
142 traits::EnableIfIsType<T, ast::Node>* create() {
143 AssertNotMoved();
144 return nodes_.Create<T>(source_);
145 }
146
147 /// creates a new ast::Node owned by the Module, injecting the current Source
148 /// as set by the last call to SetSource() as the first argument to the
149 /// constructor.
150 /// When the Module is destructed, the ast::Node will also be destructed.
151 /// @param arg0 the first arguments to pass to the type constructor
152 /// @param args the remaining arguments to pass to the type constructor
153 /// @returns the node pointer
154 template <typename T, typename ARG0, typename... ARGS>
155 traits::EnableIf</* T is ast::Node and ARG0 is not Source */
156 traits::IsTypeOrDerived<T, ast::Node>::value &&
157 !traits::IsTypeOrDerived<ARG0, Source>::value,
158 T>*
159 create(ARG0&& arg0, ARGS&&... args) {
160 AssertNotMoved();
161 return nodes_.Create<T>(source_, std::forward<ARG0>(arg0),
162 std::forward<ARGS>(args)...);
163 }
164
165 /// creates a new type::Type owned by the Module.
166 /// When the Module is destructed, owned Module and the returned
167 /// `Type` will also be destructed.
168 /// Types are unique (de-aliased), and so calling create() for the same `T`
169 /// and arguments will return the same pointer.
170 /// @warning Use this method to acquire a type only if all of its type
171 /// information is provided in the constructor arguments `args`.<br>
172 /// If the type requires additional configuration after construction that
173 /// affect its fundamental type, build the type with `std::make_unique`, make
174 /// any necessary alterations and then call unique_type() instead.
175 /// @param args the arguments to pass to the type constructor
176 /// @returns the de-aliased type pointer
177 template <typename T, typename... ARGS>
178 traits::EnableIfIsType<T, type::Type>* create(ARGS&&... args) {
179 static_assert(std::is_base_of<type::Type, T>::value,
180 "T does not derive from type::Type");
181 AssertNotMoved();
182 return types_.Get<T>(std::forward<ARGS>(args)...);
183 }
184
185 /// Marks this builder as moved, preventing any further use of the builder.
186 void MarkAsMoved();
187
188 //////////////////////////////////////////////////////////////////////////////
189 // TypesBuilder
190 //////////////////////////////////////////////////////////////////////////////
191
192 /// TypesBuilder holds basic `tint` types and methods for constructing
193 /// complex types.
194 class TypesBuilder {
195 public:
196 /// Constructor
197 /// @param builder the program builder
198 explicit TypesBuilder(ProgramBuilder* builder);
199
200 /// @return the tint AST type for the C type `T`.
201 template <typename T>
202 type::Type* Of() const {
203 return CToAST<T>::get(this);
204 }
205
206 /// @returns a boolean type
207 type::Bool* bool_() const { return builder->create<type::Bool>(); }
208
209 /// @returns a f32 type
210 type::F32* f32() const { return builder->create<type::F32>(); }
211
212 /// @returns a i32 type
213 type::I32* i32() const { return builder->create<type::I32>(); }
214
215 /// @returns a u32 type
216 type::U32* u32() const { return builder->create<type::U32>(); }
217
218 /// @returns a void type
219 type::Void* void_() const { return builder->create<type::Void>(); }
220
221 /// @return the tint AST type for a 2-element vector of the C type `T`.
222 template <typename T>
223 type::Vector* vec2() const {
224 return builder->create<type::Vector>(Of<T>(), 2);
225 }
226
227 /// @return the tint AST type for a 3-element vector of the C type `T`.
228 template <typename T>
229 type::Vector* vec3() const {
230 return builder->create<type::Vector>(Of<T>(), 3);
231 }
232
233 /// @return the tint AST type for a 4-element vector of the C type `T`.
234 template <typename T>
235 type::Type* vec4() const {
236 return builder->create<type::Vector>(Of<T>(), 4);
237 }
238
239 /// @return the tint AST type for a 2x3 matrix of the C type `T`.
240 template <typename T>
241 type::Matrix* mat2x2() const {
242 return builder->create<type::Matrix>(Of<T>(), 2, 2);
243 }
244
245 /// @return the tint AST type for a 2x3 matrix of the C type `T`.
246 template <typename T>
247 type::Matrix* mat2x3() const {
248 return builder->create<type::Matrix>(Of<T>(), 3, 2);
249 }
250
251 /// @return the tint AST type for a 2x4 matrix of the C type `T`.
252 template <typename T>
253 type::Matrix* mat2x4() const {
254 return builder->create<type::Matrix>(Of<T>(), 4, 2);
255 }
256
257 /// @return the tint AST type for a 3x2 matrix of the C type `T`.
258 template <typename T>
259 type::Matrix* mat3x2() const {
260 return builder->create<type::Matrix>(Of<T>(), 2, 3);
261 }
262
263 /// @return the tint AST type for a 3x3 matrix of the C type `T`.
264 template <typename T>
265 type::Matrix* mat3x3() const {
266 return builder->create<type::Matrix>(Of<T>(), 3, 3);
267 }
268
269 /// @return the tint AST type for a 3x4 matrix of the C type `T`.
270 template <typename T>
271 type::Matrix* mat3x4() const {
272 return builder->create<type::Matrix>(Of<T>(), 4, 3);
273 }
274
275 /// @return the tint AST type for a 4x2 matrix of the C type `T`.
276 template <typename T>
277 type::Matrix* mat4x2() const {
278 return builder->create<type::Matrix>(Of<T>(), 2, 4);
279 }
280
281 /// @return the tint AST type for a 4x3 matrix of the C type `T`.
282 template <typename T>
283 type::Matrix* mat4x3() const {
284 return builder->create<type::Matrix>(Of<T>(), 3, 4);
285 }
286
287 /// @return the tint AST type for a 4x4 matrix of the C type `T`.
288 template <typename T>
289 type::Matrix* mat4x4() const {
290 return builder->create<type::Matrix>(Of<T>(), 4, 4);
291 }
292
293 /// @param subtype the array element type
294 /// @param n the array size. 0 represents a runtime-array.
295 /// @return the tint AST type for a array of size `n` of type `T`
296 type::Array* array(type::Type* subtype, uint32_t n) const {
297 return builder->create<type::Array>(subtype, n,
298 ast::ArrayDecorationList{});
299 }
300
301 /// @return the tint AST type for an array of size `N` of type `T`
302 template <typename T, int N = 0>
303 type::Array* array() const {
304 return array(Of<T>(), N);
305 }
306
307 /// creates an alias type
308 /// @param name the alias name
309 /// @param type the alias type
310 /// @returns the alias pointer
311 type::Alias* alias(const std::string& name, type::Type* type) const {
312 return builder->create<type::Alias>(builder->Symbols().Register(name),
313 type);
314 }
315
316 /// @return the tint AST pointer to type `T` with the given
317 /// ast::StorageClass.
318 /// @param storage_class the storage class of the pointer
319 template <typename T>
320 type::Pointer* pointer(ast::StorageClass storage_class) const {
321 return builder->create<type::Pointer>(Of<T>(), storage_class);
322 }
323
324 /// @param name the struct name
325 /// @param impl the struct implementation
326 /// @returns a struct pointer
327 type::Struct* struct_(const std::string& name, ast::Struct* impl) const {
328 return builder->create<type::Struct>(builder->Symbols().Register(name),
329 impl);
330 }
331
332 private:
333 /// CToAST<T> is specialized for various `T` types and each specialization
334 /// contains a single static `get()` method for obtaining the corresponding
335 /// AST type for the C type `T`.
336 /// `get()` has the signature:
337 /// `static type::Type* get(Types* t)`
338 template <typename T>
339 struct CToAST {};
340
341 ProgramBuilder* builder;
342 };
343
344 //////////////////////////////////////////////////////////////////////////////
345 // AST helper methods
346 //////////////////////////////////////////////////////////////////////////////
347
348 /// @param expr the expression
349 /// @return expr
350 ast::Expression* Expr(ast::Expression* expr) { return expr; }
351
352 /// @param name the identifier name
353 /// @return an ast::IdentifierExpression with the given name
354 ast::IdentifierExpression* Expr(const std::string& name) {
355 return create<ast::IdentifierExpression>(Symbols().Register(name));
356 }
357
358 /// @param source the source information
359 /// @param name the identifier name
360 /// @return an ast::IdentifierExpression with the given name
361 ast::IdentifierExpression* Expr(const Source& source,
362 const std::string& name) {
363 return create<ast::IdentifierExpression>(source, Symbols().Register(name));
364 }
365
366 /// @param name the identifier name
367 /// @return an ast::IdentifierExpression with the given name
368 ast::IdentifierExpression* Expr(const char* name) {
369 return create<ast::IdentifierExpression>(Symbols().Register(name));
370 }
371
372 /// @param value the boolean value
373 /// @return a Scalar constructor for the given value
374 ast::ScalarConstructorExpression* Expr(bool value) {
375 return create<ast::ScalarConstructorExpression>(Literal(value));
376 }
377
378 /// @param value the float value
379 /// @return a Scalar constructor for the given value
380 ast::ScalarConstructorExpression* Expr(f32 value) {
381 return create<ast::ScalarConstructorExpression>(Literal(value));
382 }
383
384 /// @param value the integer value
385 /// @return a Scalar constructor for the given value
386 ast::ScalarConstructorExpression* Expr(i32 value) {
387 return create<ast::ScalarConstructorExpression>(Literal(value));
388 }
389
390 /// @param value the unsigned int value
391 /// @return a Scalar constructor for the given value
392 ast::ScalarConstructorExpression* Expr(u32 value) {
393 return create<ast::ScalarConstructorExpression>(Literal(value));
394 }
395
396 /// Converts `arg` to an `ast::Expression` using `Expr()`, then appends it to
397 /// `list`.
398 /// @param list the list to append too
399 /// @param arg the arg to create
400 template <typename ARG>
401 void Append(ast::ExpressionList& list, ARG&& arg) {
402 list.emplace_back(Expr(std::forward<ARG>(arg)));
403 }
404
405 /// Converts `arg0` and `args` to `ast::Expression`s using `Expr()`,
406 /// then appends them to `list`.
407 /// @param list the list to append too
408 /// @param arg0 the first argument
409 /// @param args the rest of the arguments
410 template <typename ARG0, typename... ARGS>
411 void Append(ast::ExpressionList& list, ARG0&& arg0, ARGS&&... args) {
412 Append(list, std::forward<ARG0>(arg0));
413 Append(list, std::forward<ARGS>(args)...);
414 }
415
416 /// @return an empty list of expressions
417 ast::ExpressionList ExprList() { return {}; }
418
419 /// @param args the list of expressions
420 /// @return the list of expressions converted to `ast::Expression`s using
421 /// `Expr()`,
422 template <typename... ARGS>
423 ast::ExpressionList ExprList(ARGS&&... args) {
424 ast::ExpressionList list;
425 list.reserve(sizeof...(args));
426 Append(list, std::forward<ARGS>(args)...);
427 return list;
428 }
429
430 /// @param list the list of expressions
431 /// @return `list`
432 ast::ExpressionList ExprList(ast::ExpressionList list) { return list; }
433
434 /// @param val the boolan value
435 /// @return a boolean literal with the given value
436 ast::BoolLiteral* Literal(bool val) {
437 return create<ast::BoolLiteral>(ty.bool_(), val);
438 }
439
440 /// @param val the float value
441 /// @return a float literal with the given value
442 ast::FloatLiteral* Literal(f32 val) {
443 return create<ast::FloatLiteral>(ty.f32(), val);
444 }
445
446 /// @param val the unsigned int value
447 /// @return a ast::UintLiteral with the given value
448 ast::UintLiteral* Literal(u32 val) {
449 return create<ast::UintLiteral>(ty.u32(), val);
450 }
451
452 /// @param val the integer value
453 /// @return the ast::SintLiteral with the given value
454 ast::SintLiteral* Literal(i32 val) {
455 return create<ast::SintLiteral>(ty.i32(), val);
456 }
457
458 /// @param args the arguments for the type constructor
459 /// @return an `ast::TypeConstructorExpression` of type `ty`, with the values
460 /// of `args` converted to `ast::Expression`s using `Expr()`
461 template <typename T, typename... ARGS>
462 ast::TypeConstructorExpression* Construct(ARGS&&... args) {
463 return create<ast::TypeConstructorExpression>(
464 ty.Of<T>(), ExprList(std::forward<ARGS>(args)...));
465 }
466
467 /// @param type the type to construct
468 /// @param args the arguments for the constructor
469 /// @return an `ast::TypeConstructorExpression` of `type` constructed with the
470 /// values `args`.
471 template <typename... ARGS>
472 ast::TypeConstructorExpression* Construct(type::Type* type, ARGS&&... args) {
473 return create<ast::TypeConstructorExpression>(
474 type, ExprList(std::forward<ARGS>(args)...));
475 }
476
477 /// @param args the arguments for the vector constructor
478 /// @return an `ast::TypeConstructorExpression` of a 2-element vector of type
479 /// `T`, constructed with the values `args`.
480 template <typename T, typename... ARGS>
481 ast::TypeConstructorExpression* vec2(ARGS&&... args) {
482 return create<ast::TypeConstructorExpression>(
483 ty.vec2<T>(), ExprList(std::forward<ARGS>(args)...));
484 }
485
486 /// @param args the arguments for the vector constructor
487 /// @return an `ast::TypeConstructorExpression` of a 3-element vector of type
488 /// `T`, constructed with the values `args`.
489 template <typename T, typename... ARGS>
490 ast::TypeConstructorExpression* vec3(ARGS&&... args) {
491 return create<ast::TypeConstructorExpression>(
492 ty.vec3<T>(), ExprList(std::forward<ARGS>(args)...));
493 }
494
495 /// @param args the arguments for the vector constructor
496 /// @return an `ast::TypeConstructorExpression` of a 4-element vector of type
497 /// `T`, constructed with the values `args`.
498 template <typename T, typename... ARGS>
499 ast::TypeConstructorExpression* vec4(ARGS&&... args) {
500 return create<ast::TypeConstructorExpression>(
501 ty.vec4<T>(), ExprList(std::forward<ARGS>(args)...));
502 }
503
504 /// @param args the arguments for the matrix constructor
505 /// @return an `ast::TypeConstructorExpression` of a 2x2 matrix of type
506 /// `T`, constructed with the values `args`.
507 template <typename T, typename... ARGS>
508 ast::TypeConstructorExpression* mat2x2(ARGS&&... args) {
509 return create<ast::TypeConstructorExpression>(
510 ty.mat2x2<T>(), ExprList(std::forward<ARGS>(args)...));
511 }
512
513 /// @param args the arguments for the matrix constructor
514 /// @return an `ast::TypeConstructorExpression` of a 2x3 matrix of type
515 /// `T`, constructed with the values `args`.
516 template <typename T, typename... ARGS>
517 ast::TypeConstructorExpression* mat2x3(ARGS&&... args) {
518 return create<ast::TypeConstructorExpression>(
519 ty.mat2x3<T>(), ExprList(std::forward<ARGS>(args)...));
520 }
521
522 /// @param args the arguments for the matrix constructor
523 /// @return an `ast::TypeConstructorExpression` of a 2x4 matrix of type
524 /// `T`, constructed with the values `args`.
525 template <typename T, typename... ARGS>
526 ast::TypeConstructorExpression* mat2x4(ARGS&&... args) {
527 return create<ast::TypeConstructorExpression>(
528 ty.mat2x4<T>(), ExprList(std::forward<ARGS>(args)...));
529 }
530
531 /// @param args the arguments for the matrix constructor
532 /// @return an `ast::TypeConstructorExpression` of a 3x2 matrix of type
533 /// `T`, constructed with the values `args`.
534 template <typename T, typename... ARGS>
535 ast::TypeConstructorExpression* mat3x2(ARGS&&... args) {
536 return create<ast::TypeConstructorExpression>(
537 ty.mat3x2<T>(), ExprList(std::forward<ARGS>(args)...));
538 }
539
540 /// @param args the arguments for the matrix constructor
541 /// @return an `ast::TypeConstructorExpression` of a 3x3 matrix of type
542 /// `T`, constructed with the values `args`.
543 template <typename T, typename... ARGS>
544 ast::TypeConstructorExpression* mat3x3(ARGS&&... args) {
545 return create<ast::TypeConstructorExpression>(
546 ty.mat3x3<T>(), ExprList(std::forward<ARGS>(args)...));
547 }
548
549 /// @param args the arguments for the matrix constructor
550 /// @return an `ast::TypeConstructorExpression` of a 3x4 matrix of type
551 /// `T`, constructed with the values `args`.
552 template <typename T, typename... ARGS>
553 ast::TypeConstructorExpression* mat3x4(ARGS&&... args) {
554 return create<ast::TypeConstructorExpression>(
555 ty.mat3x4<T>(), ExprList(std::forward<ARGS>(args)...));
556 }
557
558 /// @param args the arguments for the matrix constructor
559 /// @return an `ast::TypeConstructorExpression` of a 4x2 matrix of type
560 /// `T`, constructed with the values `args`.
561 template <typename T, typename... ARGS>
562 ast::TypeConstructorExpression* mat4x2(ARGS&&... args) {
563 return create<ast::TypeConstructorExpression>(
564 ty.mat4x2<T>(), ExprList(std::forward<ARGS>(args)...));
565 }
566
567 /// @param args the arguments for the matrix constructor
568 /// @return an `ast::TypeConstructorExpression` of a 4x3 matrix of type
569 /// `T`, constructed with the values `args`.
570 template <typename T, typename... ARGS>
571 ast::TypeConstructorExpression* mat4x3(ARGS&&... args) {
572 return create<ast::TypeConstructorExpression>(
573 ty.mat4x3<T>(), ExprList(std::forward<ARGS>(args)...));
574 }
575
576 /// @param args the arguments for the matrix constructor
577 /// @return an `ast::TypeConstructorExpression` of a 4x4 matrix of type
578 /// `T`, constructed with the values `args`.
579 template <typename T, typename... ARGS>
580 ast::TypeConstructorExpression* mat4x4(ARGS&&... args) {
581 return create<ast::TypeConstructorExpression>(
582 ty.mat4x4<T>(), ExprList(std::forward<ARGS>(args)...));
583 }
584
585 /// @param args the arguments for the array constructor
586 /// @return an `ast::TypeConstructorExpression` of an array with element type
587 /// `T`, constructed with the values `args`.
588 template <typename T, int N = 0, typename... ARGS>
589 ast::TypeConstructorExpression* array(ARGS&&... args) {
590 return create<ast::TypeConstructorExpression>(
591 ty.array<T, N>(), ExprList(std::forward<ARGS>(args)...));
592 }
593
594 /// @param subtype the array element type
595 /// @param n the array size. 0 represents a runtime-array.
596 /// @param args the arguments for the array constructor
597 /// @return an `ast::TypeConstructorExpression` of an array with element type
598 /// `subtype`, constructed with the values `args`.
599 template <typename... ARGS>
600 ast::TypeConstructorExpression* array(type::Type* subtype,
601 uint32_t n,
602 ARGS&&... args) {
603 return create<ast::TypeConstructorExpression>(
604 ty.array(subtype, n), ExprList(std::forward<ARGS>(args)...));
605 }
606
607 /// @param name the variable name
608 /// @param storage the variable storage class
609 /// @param type the variable type
610 /// @returns a `ast::Variable` with the given name, storage and type. The
611 /// variable will be built with a nullptr constructor and no decorations.
612 ast::Variable* Var(const std::string& name,
613 ast::StorageClass storage,
614 type::Type* type);
615
616 /// @param name the variable name
617 /// @param storage the variable storage class
618 /// @param type the variable type
619 /// @param constructor constructor expression
620 /// @param decorations variable decorations
621 /// @returns a `ast::Variable` with the given name, storage and type
622 ast::Variable* Var(const std::string& name,
623 ast::StorageClass storage,
624 type::Type* type,
625 ast::Expression* constructor,
626 ast::VariableDecorationList decorations);
627
628 /// @param source the variable source
629 /// @param name the variable name
630 /// @param storage the variable storage class
631 /// @param type the variable type
632 /// @param constructor constructor expression
633 /// @param decorations variable decorations
634 /// @returns a `ast::Variable` with the given name, storage and type
635 ast::Variable* Var(const Source& source,
636 const std::string& name,
637 ast::StorageClass storage,
638 type::Type* type,
639 ast::Expression* constructor,
640 ast::VariableDecorationList decorations);
641
642 /// @param name the variable name
643 /// @param storage the variable storage class
644 /// @param type the variable type
645 /// @returns a constant `ast::Variable` with the given name, storage and type.
646 /// The variable will be built with a nullptr constructor and no decorations.
647 ast::Variable* Const(const std::string& name,
648 ast::StorageClass storage,
649 type::Type* type);
650
651 /// @param name the variable name
652 /// @param storage the variable storage class
653 /// @param type the variable type
654 /// @param constructor optional constructor expression
655 /// @param decorations optional variable decorations
656 /// @returns a constant `ast::Variable` with the given name, storage and type
657 ast::Variable* Const(const std::string& name,
658 ast::StorageClass storage,
659 type::Type* type,
660 ast::Expression* constructor,
661 ast::VariableDecorationList decorations);
662
663 /// @param source the variable source
664 /// @param name the variable name
665 /// @param storage the variable storage class
666 /// @param type the variable type
667 /// @param constructor optional constructor expression
668 /// @param decorations optional variable decorations
669 /// @returns a constant `ast::Variable` with the given name, storage and type
670 ast::Variable* Const(const Source& source,
671 const std::string& name,
672 ast::StorageClass storage,
673 type::Type* type,
674 ast::Expression* constructor,
675 ast::VariableDecorationList decorations);
676
677 /// @param func the function name
678 /// @param args the function call arguments
679 /// @returns a `ast::CallExpression` to the function `func`, with the
680 /// arguments of `args` converted to `ast::Expression`s using `Expr()`.
681 template <typename NAME, typename... ARGS>
682 ast::CallExpression* Call(NAME&& func, ARGS&&... args) {
683 return create<ast::CallExpression>(Expr(func),
684 ExprList(std::forward<ARGS>(args)...));
685 }
686
687 /// @param lhs the left hand argument to the addition operation
688 /// @param rhs the right hand argument to the addition operation
689 /// @returns a `ast::BinaryExpression` summing the arguments `lhs` and `rhs`
690 template <typename LHS, typename RHS>
691 ast::Expression* Add(LHS&& lhs, RHS&& rhs) {
692 return create<ast::BinaryExpression>(ast::BinaryOp::kAdd,
693 Expr(std::forward<LHS>(lhs)),
694 Expr(std::forward<RHS>(rhs)));
695 }
696
697 /// @param lhs the left hand argument to the subtraction operation
698 /// @param rhs the right hand argument to the subtraction operation
699 /// @returns a `ast::BinaryExpression` subtracting `rhs` from `lhs`
700 template <typename LHS, typename RHS>
701 ast::Expression* Sub(LHS&& lhs, RHS&& rhs) {
702 return create<ast::BinaryExpression>(ast::BinaryOp::kSubtract,
703 Expr(std::forward<LHS>(lhs)),
704 Expr(std::forward<RHS>(rhs)));
705 }
706
707 /// @param lhs the left hand argument to the multiplication operation
708 /// @param rhs the right hand argument to the multiplication operation
709 /// @returns a `ast::BinaryExpression` multiplying `rhs` from `lhs`
710 template <typename LHS, typename RHS>
711 ast::Expression* Mul(LHS&& lhs, RHS&& rhs) {
712 return create<ast::BinaryExpression>(ast::BinaryOp::kMultiply,
713 Expr(std::forward<LHS>(lhs)),
714 Expr(std::forward<RHS>(rhs)));
715 }
716
717 /// @param arr the array argument for the array accessor expression
718 /// @param idx the index argument for the array accessor expression
719 /// @returns a `ast::ArrayAccessorExpression` that indexes `arr` with `idx`
720 template <typename ARR, typename IDX>
721 ast::Expression* IndexAccessor(ARR&& arr, IDX&& idx) {
722 return create<ast::ArrayAccessorExpression>(Expr(std::forward<ARR>(arr)),
723 Expr(std::forward<IDX>(idx)));
724 }
725
726 /// @param obj the object for the member accessor expression
727 /// @param idx the index argument for the array accessor expression
728 /// @returns a `ast::MemberAccessorExpression` that indexes `obj` with `idx`
729 template <typename OBJ, typename IDX>
730 ast::Expression* MemberAccessor(OBJ&& obj, IDX&& idx) {
731 return create<ast::MemberAccessorExpression>(Expr(std::forward<OBJ>(obj)),
732 Expr(std::forward<IDX>(idx)));
733 }
734
735 /// creates a ast::StructMemberOffsetDecoration
736 /// @param val the offset value
737 /// @returns the offset decoration pointer
738 ast::StructMemberOffsetDecoration* MemberOffset(uint32_t val) {
739 return create<ast::StructMemberOffsetDecoration>(source_, val);
740 }
741
742 /// creates a ast::Function
743 /// @param source the source information
744 /// @param name the function name
745 /// @param params the function parameters
746 /// @param type the function return type
747 /// @param body the function body
748 /// @param decorations the function decorations
749 /// @returns the function pointer
750 ast::Function* Func(Source source,
751 std::string name,
752 ast::VariableList params,
753 type::Type* type,
754 ast::StatementList body,
755 ast::FunctionDecorationList decorations) {
756 return create<ast::Function>(source, Symbols().Register(name), params, type,
757 create<ast::BlockStatement>(body),
758 decorations);
759 }
760
761 /// creates a ast::Function
762 /// @param name the function name
763 /// @param params the function parameters
764 /// @param type the function return type
765 /// @param body the function body
766 /// @param decorations the function decorations
767 /// @returns the function pointer
768 ast::Function* Func(std::string name,
769 ast::VariableList params,
770 type::Type* type,
771 ast::StatementList body,
772 ast::FunctionDecorationList decorations) {
773 return create<ast::Function>(Symbols().Register(name), params, type,
774 create<ast::BlockStatement>(body),
775 decorations);
776 }
777
778 /// creates a ast::StructMember
779 /// @param source the source information
780 /// @param name the struct member name
781 /// @param type the struct member type
782 /// @returns the struct member pointer
783 ast::StructMember* Member(const Source& source,
784 const std::string& name,
785 type::Type* type) {
786 return create<ast::StructMember>(source, Symbols().Register(name), type,
787 ast::StructMemberDecorationList{});
788 }
789
790 /// creates a ast::StructMember
791 /// @param name the struct member name
792 /// @param type the struct member type
793 /// @returns the struct member pointer
794 ast::StructMember* Member(const std::string& name, type::Type* type) {
795 return create<ast::StructMember>(source_, Symbols().Register(name), type,
796 ast::StructMemberDecorationList{});
797 }
798
799 /// creates a ast::StructMember
800 /// @param name the struct member name
801 /// @param type the struct member type
802 /// @param decorations the struct member decorations
803 /// @returns the struct member pointer
804 ast::StructMember* Member(const std::string& name,
805 type::Type* type,
806 ast::StructMemberDecorationList decorations) {
807 return create<ast::StructMember>(source_, Symbols().Register(name), type,
808 decorations);
809 }
810
811 /// Sets the current builder source to `src`
812 /// @param src the Source used for future create() calls
813 void SetSource(const Source& src) {
814 AssertNotMoved();
815 source_ = src;
816 }
817
818 /// Sets the current builder source to `loc`
819 /// @param loc the Source used for future create() calls
820 void SetSource(const Source::Location& loc) {
821 AssertNotMoved();
822 source_ = Source(loc);
823 }
824
825 /// The builder types
826 TypesBuilder ty;
827
828 protected:
829 /// Asserts that the builder has not been moved.
830 void AssertNotMoved() const;
831
832 /// Called whenever a new variable is built with `Var()`.
833 virtual void OnVariableBuilt(ast::Variable*) {}
834
835 private:
836 type::Manager types_;
837 ASTNodes nodes_;
838 ast::Module* ast_;
839 SymbolTable symbols_;
840
841 /// The source to use when creating AST nodes without providing a Source as
842 /// the first argument.
843 Source source_;
844
845 /// Set by MarkAsMoved(). Once set, no methods may be called on this builder.
846 bool moved_ = false;
847};
848
849//! @cond Doxygen_Suppress
850// Various template specializations for ProgramBuilder::TypesBuilder::CToAST.
851template <>
852struct ProgramBuilder::TypesBuilder::CToAST<ProgramBuilder::i32> {
853 static type::Type* get(const ProgramBuilder::TypesBuilder* t) {
854 return t->i32();
855 }
856};
857template <>
858struct ProgramBuilder::TypesBuilder::CToAST<ProgramBuilder::u32> {
859 static type::Type* get(const ProgramBuilder::TypesBuilder* t) {
860 return t->u32();
861 }
862};
863template <>
864struct ProgramBuilder::TypesBuilder::CToAST<ProgramBuilder::f32> {
865 static type::Type* get(const ProgramBuilder::TypesBuilder* t) {
866 return t->f32();
867 }
868};
869template <>
870struct ProgramBuilder::TypesBuilder::CToAST<bool> {
871 static type::Type* get(const ProgramBuilder::TypesBuilder* t) {
872 return t->bool_();
873 }
874};
875template <>
876struct ProgramBuilder::TypesBuilder::CToAST<void> {
877 static type::Type* get(const ProgramBuilder::TypesBuilder* t) {
878 return t->void_();
879 }
880};
881//! @endcond
882
883} // namespace tint
884
885#endif // SRC_PROGRAM_BUILDER_H_