blob: a993063b716246e618d1a0d7ac84ae6e446b98e5 [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"
Ben Clayton844217f2021-01-27 18:49:05 +000038#include "src/diagnostic/diagnostic.h"
Ben Claytona6b9a8e2021-01-26 16:57:10 +000039#include "src/program.h"
Ben Claytondd1b6fc2021-01-29 10:55:40 +000040#include "src/semantic/info.h"
Ben Clayton7fdfff12021-01-29 15:17:30 +000041#include "src/semantic/node.h"
Ben Claytona6b9a8e2021-01-26 16:57:10 +000042#include "src/symbol_table.h"
43#include "src/type/alias_type.h"
44#include "src/type/array_type.h"
45#include "src/type/bool_type.h"
46#include "src/type/f32_type.h"
47#include "src/type/i32_type.h"
48#include "src/type/matrix_type.h"
49#include "src/type/pointer_type.h"
50#include "src/type/struct_type.h"
51#include "src/type/type_manager.h"
52#include "src/type/u32_type.h"
53#include "src/type/vector_type.h"
54#include "src/type/void_type.h"
55
56namespace tint {
57
Ben Clayton401b96b2021-02-03 17:19:59 +000058// Forward declarations
59namespace ast {
60class VariableDeclStatement;
61} // namespace ast
62
Ben Claytona6b9a8e2021-01-26 16:57:10 +000063class CloneContext;
64
65/// ProgramBuilder is a mutable builder for a Program.
66/// To construct a Program, populate the builder and then `std::move` it to a
67/// Program.
68class ProgramBuilder {
69 public:
Ben Clayton7fdfff12021-01-29 15:17:30 +000070 /// ASTNodeAllocator is an alias to BlockAllocator<ast::Node>
71 using ASTNodeAllocator = BlockAllocator<ast::Node>;
72
73 /// SemNodeAllocator is an alias to BlockAllocator<semantic::Node>
74 using SemNodeAllocator = BlockAllocator<semantic::Node>;
Ben Claytona6b9a8e2021-01-26 16:57:10 +000075
76 /// `i32` is a type alias to `int`.
77 /// Useful for passing to template methods such as `vec2<i32>()` to imitate
78 /// WGSL syntax.
79 /// Note: this is intentionally not aliased to uint32_t as we want integer
80 /// literals passed to the builder to match WGSL's integer literal types.
81 using i32 = decltype(1);
82 /// `u32` is a type alias to `unsigned int`.
83 /// Useful for passing to template methods such as `vec2<u32>()` to imitate
84 /// WGSL syntax.
85 /// Note: this is intentionally not aliased to uint32_t as we want integer
86 /// literals passed to the builder to match WGSL's integer literal types.
87 using u32 = decltype(1u);
88 /// `f32` is a type alias to `float`
89 /// Useful for passing to template methods such as `vec2<f32>()` to imitate
90 /// WGSL syntax.
91 using f32 = float;
92
93 /// Constructor
94 ProgramBuilder();
95
96 /// Move constructor
97 /// @param rhs the builder to move
98 ProgramBuilder(ProgramBuilder&& rhs);
99
100 /// Destructor
101 virtual ~ProgramBuilder();
102
103 /// Move assignment operator
104 /// @param rhs the builder to move
105 /// @return this builder
106 ProgramBuilder& operator=(ProgramBuilder&& rhs);
107
Ben Claytone43c8302021-01-29 11:59:32 +0000108 /// Wrap returns a new ProgramBuilder wrapping the Program `program` without
109 /// making a deep clone of the Program contents.
110 /// ProgramBuilder returned by Wrap() is intended to temporarily extend an
111 /// existing immutable program.
112 /// As the returned ProgramBuilder wraps `program`, `program` must not be
113 /// destructed or assigned while using the returned ProgramBuilder.
114 /// TODO(bclayton) - Evaluate whether there are safer alternatives to this
115 /// function. See crbug.com/tint/460.
116 /// @param program the immutable Program to wrap
117 /// @return the ProgramBuilder that wraps `program`
118 static ProgramBuilder Wrap(const Program* program);
119
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000120 /// @returns a reference to the program's types
121 type::Manager& Types() {
122 AssertNotMoved();
123 return types_;
124 }
125
Ben Claytondd1b6fc2021-01-29 10:55:40 +0000126 /// @returns a reference to the program's types
127 const type::Manager& Types() const {
128 AssertNotMoved();
129 return types_;
130 }
131
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000132 /// @returns a reference to the program's AST nodes storage
Ben Clayton7fdfff12021-01-29 15:17:30 +0000133 ASTNodeAllocator& ASTNodes() {
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000134 AssertNotMoved();
Ben Clayton7fdfff12021-01-29 15:17:30 +0000135 return ast_nodes_;
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000136 }
137
Ben Claytondd1b6fc2021-01-29 10:55:40 +0000138 /// @returns a reference to the program's AST nodes storage
Ben Clayton7fdfff12021-01-29 15:17:30 +0000139 const ASTNodeAllocator& ASTNodes() const {
Ben Claytondd1b6fc2021-01-29 10:55:40 +0000140 AssertNotMoved();
Ben Clayton7fdfff12021-01-29 15:17:30 +0000141 return ast_nodes_;
142 }
143
144 /// @returns a reference to the program's semantic nodes storage
145 SemNodeAllocator& SemNodes() {
146 AssertNotMoved();
147 return sem_nodes_;
148 }
149
150 /// @returns a reference to the program's semantic nodes storage
151 const SemNodeAllocator& SemNodes() const {
152 AssertNotMoved();
153 return sem_nodes_;
Ben Claytondd1b6fc2021-01-29 10:55:40 +0000154 }
155
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000156 /// @returns a reference to the program's AST root Module
157 ast::Module& AST() {
158 AssertNotMoved();
159 return *ast_;
160 }
161
Ben Claytondd1b6fc2021-01-29 10:55:40 +0000162 /// @returns a reference to the program's AST root Module
163 const ast::Module& AST() const {
164 AssertNotMoved();
165 return *ast_;
166 }
167
168 /// @returns a reference to the program's semantic info
169 semantic::Info& Sem() {
170 AssertNotMoved();
171 return sem_;
172 }
173
174 /// @returns a reference to the program's semantic info
175 const semantic::Info& Sem() const {
176 AssertNotMoved();
177 return sem_;
178 }
179
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000180 /// @returns a reference to the program's SymbolTable
181 SymbolTable& Symbols() {
182 AssertNotMoved();
183 return symbols_;
184 }
185
Ben Clayton708dc2d2021-01-29 11:22:40 +0000186 /// @returns a reference to the program's SymbolTable
187 const SymbolTable& Symbols() const {
188 AssertNotMoved();
189 return symbols_;
190 }
191
Ben Clayton844217f2021-01-27 18:49:05 +0000192 /// @returns a reference to the program's diagnostics
193 diag::List& Diagnostics() {
194 AssertNotMoved();
195 return diagnostics_;
196 }
197
Ben Claytondd1b6fc2021-01-29 10:55:40 +0000198 /// @returns a reference to the program's diagnostics
199 const diag::List& Diagnostics() const {
200 AssertNotMoved();
201 return diagnostics_;
202 }
203
Ben Claytondd69ac32021-01-27 19:23:55 +0000204 /// Controls whether the TypeDeterminer will be run on the program when it is
205 /// built.
206 /// @param enable the new flag value (defaults to true)
207 void SetResolveOnBuild(bool enable) { resolve_on_build_ = enable; }
208
209 /// @return true if the TypeDeterminer will be run on the program when it is
210 /// built.
211 bool ResolveOnBuild() const { return resolve_on_build_; }
212
Ben Clayton844217f2021-01-27 18:49:05 +0000213 /// @returns true if the program has no error diagnostics and is not missing
214 /// information
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000215 bool IsValid() const;
216
Ben Clayton708dc2d2021-01-29 11:22:40 +0000217 /// Writes a representation of the node to the output stream
218 /// @note unlike str(), to_str() does not automatically demangle the string.
219 /// @param node the AST node
220 /// @param out the stream to write to
221 /// @param indent number of spaces to indent the node when writing
222 void to_str(const ast::Node* node, std::ostream& out, size_t indent) const {
223 node->to_str(Sem(), out, indent);
224 }
225
226 /// Returns a demangled, string representation of `node`.
227 /// @param node the AST node
228 /// @returns a string representation of the node
229 std::string str(const ast::Node* node) const;
230
Ben Clayton7fdfff12021-01-29 15:17:30 +0000231 /// Creates a new ast::Node owned by the ProgramBuilder. When the
232 /// ProgramBuilder is destructed, the ast::Node will also be destructed.
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000233 /// @param source the Source of the node
234 /// @param args the arguments to pass to the type constructor
235 /// @returns the node pointer
236 template <typename T, typename... ARGS>
237 traits::EnableIfIsType<T, ast::Node>* create(const Source& source,
238 ARGS&&... args) {
239 AssertNotMoved();
Ben Clayton7fdfff12021-01-29 15:17:30 +0000240 return ast_nodes_.Create<T>(source, std::forward<ARGS>(args)...);
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000241 }
242
Ben Clayton7fdfff12021-01-29 15:17:30 +0000243 /// Creates a new ast::Node owned by the ProgramBuilder, injecting the current
244 /// Source as set by the last call to SetSource() as the only argument to the
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000245 /// constructor.
Ben Clayton7fdfff12021-01-29 15:17:30 +0000246 /// When the ProgramBuilder is destructed, the ast::Node will also be
247 /// destructed.
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000248 /// @returns the node pointer
249 template <typename T>
250 traits::EnableIfIsType<T, ast::Node>* create() {
251 AssertNotMoved();
Ben Clayton7fdfff12021-01-29 15:17:30 +0000252 return ast_nodes_.Create<T>(source_);
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000253 }
254
Ben Clayton7fdfff12021-01-29 15:17:30 +0000255 /// Creates a new ast::Node owned by the ProgramBuilder, injecting the current
256 /// Source as set by the last call to SetSource() as the first argument to the
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000257 /// constructor.
Ben Clayton7fdfff12021-01-29 15:17:30 +0000258 /// When the ProgramBuilder is destructed, the ast::Node will also be
259 /// destructed.
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000260 /// @param arg0 the first arguments to pass to the type constructor
261 /// @param args the remaining arguments to pass to the type constructor
262 /// @returns the node pointer
263 template <typename T, typename ARG0, typename... ARGS>
264 traits::EnableIf</* T is ast::Node and ARG0 is not Source */
265 traits::IsTypeOrDerived<T, ast::Node>::value &&
266 !traits::IsTypeOrDerived<ARG0, Source>::value,
267 T>*
268 create(ARG0&& arg0, ARGS&&... args) {
269 AssertNotMoved();
Ben Clayton7fdfff12021-01-29 15:17:30 +0000270 return ast_nodes_.Create<T>(source_, std::forward<ARG0>(arg0),
271 std::forward<ARGS>(args)...);
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000272 }
273
Ben Clayton7fdfff12021-01-29 15:17:30 +0000274 /// Creates a new semantic::Node owned by the ProgramBuilder.
275 /// When the ProgramBuilder is destructed, the semantic::Node will also be
276 /// destructed.
277 /// @param args the arguments to pass to the type constructor
278 /// @returns the node pointer
279 template <typename T, typename... ARGS>
280 traits::EnableIfIsType<T, semantic::Node>* create(ARGS&&... args) {
281 AssertNotMoved();
282 return sem_nodes_.Create<T>(std::forward<ARGS>(args)...);
283 }
284
285 /// Creates a new type::Type owned by the ProgramBuilder.
286 /// When the ProgramBuilder is destructed, owned ProgramBuilder and the
287 /// returned`Type` will also be destructed.
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000288 /// Types are unique (de-aliased), and so calling create() for the same `T`
289 /// and arguments will return the same pointer.
290 /// @warning Use this method to acquire a type only if all of its type
291 /// information is provided in the constructor arguments `args`.<br>
292 /// If the type requires additional configuration after construction that
293 /// affect its fundamental type, build the type with `std::make_unique`, make
294 /// any necessary alterations and then call unique_type() instead.
295 /// @param args the arguments to pass to the type constructor
296 /// @returns the de-aliased type pointer
297 template <typename T, typename... ARGS>
298 traits::EnableIfIsType<T, type::Type>* create(ARGS&&... args) {
299 static_assert(std::is_base_of<type::Type, T>::value,
300 "T does not derive from type::Type");
301 AssertNotMoved();
302 return types_.Get<T>(std::forward<ARGS>(args)...);
303 }
304
305 /// Marks this builder as moved, preventing any further use of the builder.
306 void MarkAsMoved();
307
308 //////////////////////////////////////////////////////////////////////////////
309 // TypesBuilder
310 //////////////////////////////////////////////////////////////////////////////
311
312 /// TypesBuilder holds basic `tint` types and methods for constructing
313 /// complex types.
314 class TypesBuilder {
315 public:
316 /// Constructor
317 /// @param builder the program builder
318 explicit TypesBuilder(ProgramBuilder* builder);
319
320 /// @return the tint AST type for the C type `T`.
321 template <typename T>
322 type::Type* Of() const {
323 return CToAST<T>::get(this);
324 }
325
326 /// @returns a boolean type
327 type::Bool* bool_() const { return builder->create<type::Bool>(); }
328
329 /// @returns a f32 type
330 type::F32* f32() const { return builder->create<type::F32>(); }
331
332 /// @returns a i32 type
333 type::I32* i32() const { return builder->create<type::I32>(); }
334
335 /// @returns a u32 type
336 type::U32* u32() const { return builder->create<type::U32>(); }
337
338 /// @returns a void type
339 type::Void* void_() const { return builder->create<type::Void>(); }
340
341 /// @return the tint AST type for a 2-element vector of the C type `T`.
342 template <typename T>
343 type::Vector* vec2() const {
344 return builder->create<type::Vector>(Of<T>(), 2);
345 }
346
347 /// @return the tint AST type for a 3-element vector of the C type `T`.
348 template <typename T>
349 type::Vector* vec3() const {
350 return builder->create<type::Vector>(Of<T>(), 3);
351 }
352
353 /// @return the tint AST type for a 4-element vector of the C type `T`.
354 template <typename T>
355 type::Type* vec4() const {
356 return builder->create<type::Vector>(Of<T>(), 4);
357 }
358
359 /// @return the tint AST type for a 2x3 matrix of the C type `T`.
360 template <typename T>
361 type::Matrix* mat2x2() const {
362 return builder->create<type::Matrix>(Of<T>(), 2, 2);
363 }
364
365 /// @return the tint AST type for a 2x3 matrix of the C type `T`.
366 template <typename T>
367 type::Matrix* mat2x3() const {
368 return builder->create<type::Matrix>(Of<T>(), 3, 2);
369 }
370
371 /// @return the tint AST type for a 2x4 matrix of the C type `T`.
372 template <typename T>
373 type::Matrix* mat2x4() const {
374 return builder->create<type::Matrix>(Of<T>(), 4, 2);
375 }
376
377 /// @return the tint AST type for a 3x2 matrix of the C type `T`.
378 template <typename T>
379 type::Matrix* mat3x2() const {
380 return builder->create<type::Matrix>(Of<T>(), 2, 3);
381 }
382
383 /// @return the tint AST type for a 3x3 matrix of the C type `T`.
384 template <typename T>
385 type::Matrix* mat3x3() const {
386 return builder->create<type::Matrix>(Of<T>(), 3, 3);
387 }
388
389 /// @return the tint AST type for a 3x4 matrix of the C type `T`.
390 template <typename T>
391 type::Matrix* mat3x4() const {
392 return builder->create<type::Matrix>(Of<T>(), 4, 3);
393 }
394
395 /// @return the tint AST type for a 4x2 matrix of the C type `T`.
396 template <typename T>
397 type::Matrix* mat4x2() const {
398 return builder->create<type::Matrix>(Of<T>(), 2, 4);
399 }
400
401 /// @return the tint AST type for a 4x3 matrix of the C type `T`.
402 template <typename T>
403 type::Matrix* mat4x3() const {
404 return builder->create<type::Matrix>(Of<T>(), 3, 4);
405 }
406
407 /// @return the tint AST type for a 4x4 matrix of the C type `T`.
408 template <typename T>
409 type::Matrix* mat4x4() const {
410 return builder->create<type::Matrix>(Of<T>(), 4, 4);
411 }
412
413 /// @param subtype the array element type
414 /// @param n the array size. 0 represents a runtime-array.
415 /// @return the tint AST type for a array of size `n` of type `T`
416 type::Array* array(type::Type* subtype, uint32_t n) const {
417 return builder->create<type::Array>(subtype, n,
418 ast::ArrayDecorationList{});
419 }
420
421 /// @return the tint AST type for an array of size `N` of type `T`
422 template <typename T, int N = 0>
423 type::Array* array() const {
424 return array(Of<T>(), N);
425 }
426
Ben Clayton42d1e092021-02-02 14:29:15 +0000427 /// Creates an alias type
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000428 /// @param name the alias name
429 /// @param type the alias type
430 /// @returns the alias pointer
431 type::Alias* alias(const std::string& name, type::Type* type) const {
432 return builder->create<type::Alias>(builder->Symbols().Register(name),
433 type);
434 }
435
436 /// @return the tint AST pointer to type `T` with the given
437 /// ast::StorageClass.
438 /// @param storage_class the storage class of the pointer
439 template <typename T>
440 type::Pointer* pointer(ast::StorageClass storage_class) const {
441 return builder->create<type::Pointer>(Of<T>(), storage_class);
442 }
443
444 /// @param name the struct name
445 /// @param impl the struct implementation
446 /// @returns a struct pointer
447 type::Struct* struct_(const std::string& name, ast::Struct* impl) const {
448 return builder->create<type::Struct>(builder->Symbols().Register(name),
449 impl);
450 }
451
452 private:
453 /// CToAST<T> is specialized for various `T` types and each specialization
454 /// contains a single static `get()` method for obtaining the corresponding
455 /// AST type for the C type `T`.
456 /// `get()` has the signature:
457 /// `static type::Type* get(Types* t)`
458 template <typename T>
459 struct CToAST {};
460
461 ProgramBuilder* builder;
462 };
463
464 //////////////////////////////////////////////////////////////////////////////
465 // AST helper methods
466 //////////////////////////////////////////////////////////////////////////////
467
468 /// @param expr the expression
469 /// @return expr
470 ast::Expression* Expr(ast::Expression* expr) { return expr; }
471
472 /// @param name the identifier name
473 /// @return an ast::IdentifierExpression with the given name
474 ast::IdentifierExpression* Expr(const std::string& name) {
475 return create<ast::IdentifierExpression>(Symbols().Register(name));
476 }
477
478 /// @param source the source information
479 /// @param name the identifier name
480 /// @return an ast::IdentifierExpression with the given name
481 ast::IdentifierExpression* Expr(const Source& source,
482 const std::string& name) {
483 return create<ast::IdentifierExpression>(source, Symbols().Register(name));
484 }
485
486 /// @param name the identifier name
487 /// @return an ast::IdentifierExpression with the given name
488 ast::IdentifierExpression* Expr(const char* name) {
489 return create<ast::IdentifierExpression>(Symbols().Register(name));
490 }
491
492 /// @param value the boolean value
493 /// @return a Scalar constructor for the given value
494 ast::ScalarConstructorExpression* Expr(bool value) {
495 return create<ast::ScalarConstructorExpression>(Literal(value));
496 }
497
498 /// @param value the float value
499 /// @return a Scalar constructor for the given value
500 ast::ScalarConstructorExpression* Expr(f32 value) {
501 return create<ast::ScalarConstructorExpression>(Literal(value));
502 }
503
504 /// @param value the integer value
505 /// @return a Scalar constructor for the given value
506 ast::ScalarConstructorExpression* Expr(i32 value) {
507 return create<ast::ScalarConstructorExpression>(Literal(value));
508 }
509
510 /// @param value the unsigned int value
511 /// @return a Scalar constructor for the given value
512 ast::ScalarConstructorExpression* Expr(u32 value) {
513 return create<ast::ScalarConstructorExpression>(Literal(value));
514 }
515
516 /// Converts `arg` to an `ast::Expression` using `Expr()`, then appends it to
517 /// `list`.
518 /// @param list the list to append too
519 /// @param arg the arg to create
520 template <typename ARG>
521 void Append(ast::ExpressionList& list, ARG&& arg) {
522 list.emplace_back(Expr(std::forward<ARG>(arg)));
523 }
524
525 /// Converts `arg0` and `args` to `ast::Expression`s using `Expr()`,
526 /// then appends them to `list`.
527 /// @param list the list to append too
528 /// @param arg0 the first argument
529 /// @param args the rest of the arguments
530 template <typename ARG0, typename... ARGS>
531 void Append(ast::ExpressionList& list, ARG0&& arg0, ARGS&&... args) {
532 Append(list, std::forward<ARG0>(arg0));
533 Append(list, std::forward<ARGS>(args)...);
534 }
535
536 /// @return an empty list of expressions
537 ast::ExpressionList ExprList() { return {}; }
538
539 /// @param args the list of expressions
540 /// @return the list of expressions converted to `ast::Expression`s using
541 /// `Expr()`,
542 template <typename... ARGS>
543 ast::ExpressionList ExprList(ARGS&&... args) {
544 ast::ExpressionList list;
545 list.reserve(sizeof...(args));
546 Append(list, std::forward<ARGS>(args)...);
547 return list;
548 }
549
550 /// @param list the list of expressions
551 /// @return `list`
552 ast::ExpressionList ExprList(ast::ExpressionList list) { return list; }
553
554 /// @param val the boolan value
555 /// @return a boolean literal with the given value
556 ast::BoolLiteral* Literal(bool val) {
557 return create<ast::BoolLiteral>(ty.bool_(), val);
558 }
559
560 /// @param val the float value
561 /// @return a float literal with the given value
562 ast::FloatLiteral* Literal(f32 val) {
563 return create<ast::FloatLiteral>(ty.f32(), val);
564 }
565
566 /// @param val the unsigned int value
567 /// @return a ast::UintLiteral with the given value
568 ast::UintLiteral* Literal(u32 val) {
569 return create<ast::UintLiteral>(ty.u32(), val);
570 }
571
572 /// @param val the integer value
573 /// @return the ast::SintLiteral with the given value
574 ast::SintLiteral* Literal(i32 val) {
575 return create<ast::SintLiteral>(ty.i32(), val);
576 }
577
578 /// @param args the arguments for the type constructor
579 /// @return an `ast::TypeConstructorExpression` of type `ty`, with the values
580 /// of `args` converted to `ast::Expression`s using `Expr()`
581 template <typename T, typename... ARGS>
582 ast::TypeConstructorExpression* Construct(ARGS&&... args) {
583 return create<ast::TypeConstructorExpression>(
584 ty.Of<T>(), ExprList(std::forward<ARGS>(args)...));
585 }
586
587 /// @param type the type to construct
588 /// @param args the arguments for the constructor
589 /// @return an `ast::TypeConstructorExpression` of `type` constructed with the
590 /// values `args`.
591 template <typename... ARGS>
592 ast::TypeConstructorExpression* Construct(type::Type* type, ARGS&&... args) {
593 return create<ast::TypeConstructorExpression>(
594 type, ExprList(std::forward<ARGS>(args)...));
595 }
596
597 /// @param args the arguments for the vector constructor
598 /// @return an `ast::TypeConstructorExpression` of a 2-element vector of type
599 /// `T`, constructed with the values `args`.
600 template <typename T, typename... ARGS>
601 ast::TypeConstructorExpression* vec2(ARGS&&... args) {
602 return create<ast::TypeConstructorExpression>(
603 ty.vec2<T>(), ExprList(std::forward<ARGS>(args)...));
604 }
605
606 /// @param args the arguments for the vector constructor
607 /// @return an `ast::TypeConstructorExpression` of a 3-element vector of type
608 /// `T`, constructed with the values `args`.
609 template <typename T, typename... ARGS>
610 ast::TypeConstructorExpression* vec3(ARGS&&... args) {
611 return create<ast::TypeConstructorExpression>(
612 ty.vec3<T>(), ExprList(std::forward<ARGS>(args)...));
613 }
614
615 /// @param args the arguments for the vector constructor
616 /// @return an `ast::TypeConstructorExpression` of a 4-element vector of type
617 /// `T`, constructed with the values `args`.
618 template <typename T, typename... ARGS>
619 ast::TypeConstructorExpression* vec4(ARGS&&... args) {
620 return create<ast::TypeConstructorExpression>(
621 ty.vec4<T>(), ExprList(std::forward<ARGS>(args)...));
622 }
623
624 /// @param args the arguments for the matrix constructor
625 /// @return an `ast::TypeConstructorExpression` of a 2x2 matrix of type
626 /// `T`, constructed with the values `args`.
627 template <typename T, typename... ARGS>
628 ast::TypeConstructorExpression* mat2x2(ARGS&&... args) {
629 return create<ast::TypeConstructorExpression>(
630 ty.mat2x2<T>(), ExprList(std::forward<ARGS>(args)...));
631 }
632
633 /// @param args the arguments for the matrix constructor
634 /// @return an `ast::TypeConstructorExpression` of a 2x3 matrix of type
635 /// `T`, constructed with the values `args`.
636 template <typename T, typename... ARGS>
637 ast::TypeConstructorExpression* mat2x3(ARGS&&... args) {
638 return create<ast::TypeConstructorExpression>(
639 ty.mat2x3<T>(), ExprList(std::forward<ARGS>(args)...));
640 }
641
642 /// @param args the arguments for the matrix constructor
643 /// @return an `ast::TypeConstructorExpression` of a 2x4 matrix of type
644 /// `T`, constructed with the values `args`.
645 template <typename T, typename... ARGS>
646 ast::TypeConstructorExpression* mat2x4(ARGS&&... args) {
647 return create<ast::TypeConstructorExpression>(
648 ty.mat2x4<T>(), ExprList(std::forward<ARGS>(args)...));
649 }
650
651 /// @param args the arguments for the matrix constructor
652 /// @return an `ast::TypeConstructorExpression` of a 3x2 matrix of type
653 /// `T`, constructed with the values `args`.
654 template <typename T, typename... ARGS>
655 ast::TypeConstructorExpression* mat3x2(ARGS&&... args) {
656 return create<ast::TypeConstructorExpression>(
657 ty.mat3x2<T>(), ExprList(std::forward<ARGS>(args)...));
658 }
659
660 /// @param args the arguments for the matrix constructor
661 /// @return an `ast::TypeConstructorExpression` of a 3x3 matrix of type
662 /// `T`, constructed with the values `args`.
663 template <typename T, typename... ARGS>
664 ast::TypeConstructorExpression* mat3x3(ARGS&&... args) {
665 return create<ast::TypeConstructorExpression>(
666 ty.mat3x3<T>(), ExprList(std::forward<ARGS>(args)...));
667 }
668
669 /// @param args the arguments for the matrix constructor
670 /// @return an `ast::TypeConstructorExpression` of a 3x4 matrix of type
671 /// `T`, constructed with the values `args`.
672 template <typename T, typename... ARGS>
673 ast::TypeConstructorExpression* mat3x4(ARGS&&... args) {
674 return create<ast::TypeConstructorExpression>(
675 ty.mat3x4<T>(), ExprList(std::forward<ARGS>(args)...));
676 }
677
678 /// @param args the arguments for the matrix constructor
679 /// @return an `ast::TypeConstructorExpression` of a 4x2 matrix of type
680 /// `T`, constructed with the values `args`.
681 template <typename T, typename... ARGS>
682 ast::TypeConstructorExpression* mat4x2(ARGS&&... args) {
683 return create<ast::TypeConstructorExpression>(
684 ty.mat4x2<T>(), ExprList(std::forward<ARGS>(args)...));
685 }
686
687 /// @param args the arguments for the matrix constructor
688 /// @return an `ast::TypeConstructorExpression` of a 4x3 matrix of type
689 /// `T`, constructed with the values `args`.
690 template <typename T, typename... ARGS>
691 ast::TypeConstructorExpression* mat4x3(ARGS&&... args) {
692 return create<ast::TypeConstructorExpression>(
693 ty.mat4x3<T>(), ExprList(std::forward<ARGS>(args)...));
694 }
695
696 /// @param args the arguments for the matrix constructor
697 /// @return an `ast::TypeConstructorExpression` of a 4x4 matrix of type
698 /// `T`, constructed with the values `args`.
699 template <typename T, typename... ARGS>
700 ast::TypeConstructorExpression* mat4x4(ARGS&&... args) {
701 return create<ast::TypeConstructorExpression>(
702 ty.mat4x4<T>(), ExprList(std::forward<ARGS>(args)...));
703 }
704
705 /// @param args the arguments for the array constructor
706 /// @return an `ast::TypeConstructorExpression` of an array with element type
707 /// `T`, constructed with the values `args`.
708 template <typename T, int N = 0, typename... ARGS>
709 ast::TypeConstructorExpression* array(ARGS&&... args) {
710 return create<ast::TypeConstructorExpression>(
711 ty.array<T, N>(), ExprList(std::forward<ARGS>(args)...));
712 }
713
714 /// @param subtype the array element type
715 /// @param n the array size. 0 represents a runtime-array.
716 /// @param args the arguments for the array constructor
717 /// @return an `ast::TypeConstructorExpression` of an array with element type
718 /// `subtype`, constructed with the values `args`.
719 template <typename... ARGS>
720 ast::TypeConstructorExpression* array(type::Type* subtype,
721 uint32_t n,
722 ARGS&&... args) {
723 return create<ast::TypeConstructorExpression>(
724 ty.array(subtype, n), ExprList(std::forward<ARGS>(args)...));
725 }
726
727 /// @param name the variable name
728 /// @param storage the variable storage class
729 /// @param type the variable type
730 /// @returns a `ast::Variable` with the given name, storage and type. The
731 /// variable will be built with a nullptr constructor and no decorations.
732 ast::Variable* Var(const std::string& name,
733 ast::StorageClass storage,
734 type::Type* type);
735
736 /// @param name the variable name
737 /// @param storage the variable storage class
738 /// @param type the variable type
739 /// @param constructor constructor expression
740 /// @param decorations variable decorations
741 /// @returns a `ast::Variable` with the given name, storage and type
742 ast::Variable* Var(const std::string& name,
743 ast::StorageClass storage,
744 type::Type* type,
745 ast::Expression* constructor,
746 ast::VariableDecorationList decorations);
747
748 /// @param source the variable source
749 /// @param name the variable name
750 /// @param storage the variable storage class
751 /// @param type the variable type
752 /// @param constructor constructor expression
753 /// @param decorations variable decorations
754 /// @returns a `ast::Variable` with the given name, storage and type
755 ast::Variable* Var(const Source& source,
756 const std::string& name,
757 ast::StorageClass storage,
758 type::Type* type,
759 ast::Expression* constructor,
760 ast::VariableDecorationList decorations);
761
762 /// @param name the variable name
763 /// @param storage the variable storage class
764 /// @param type the variable type
765 /// @returns a constant `ast::Variable` with the given name, storage and type.
766 /// The variable will be built with a nullptr constructor and no decorations.
767 ast::Variable* Const(const std::string& name,
768 ast::StorageClass storage,
769 type::Type* type);
770
771 /// @param name the variable name
772 /// @param storage the variable storage class
773 /// @param type the variable type
774 /// @param constructor optional constructor expression
775 /// @param decorations optional variable decorations
776 /// @returns a constant `ast::Variable` with the given name, storage and type
777 ast::Variable* Const(const std::string& name,
778 ast::StorageClass storage,
779 type::Type* type,
780 ast::Expression* constructor,
781 ast::VariableDecorationList decorations);
782
783 /// @param source the variable source
784 /// @param name the variable name
785 /// @param storage the variable storage class
786 /// @param type the variable type
787 /// @param constructor optional constructor expression
788 /// @param decorations optional variable decorations
789 /// @returns a constant `ast::Variable` with the given name, storage and type
790 ast::Variable* Const(const Source& source,
791 const std::string& name,
792 ast::StorageClass storage,
793 type::Type* type,
794 ast::Expression* constructor,
795 ast::VariableDecorationList decorations);
796
Ben Clayton401b96b2021-02-03 17:19:59 +0000797 /// @param args the arguments to pass to Var()
798 /// @returns a `ast::Variable` constructed by calling Var() with the arguments
799 /// of `args`, which is automatically registered as a global variable with the
800 /// ast::Module.
801 template <typename... ARGS>
802 ast::Variable* Global(ARGS&&... args) {
803 auto* var = Var(std::forward<ARGS>(args)...);
804 AST().AddGlobalVariable(var);
805 return var;
806 }
807
808 /// @param args the arguments to pass to Const()
809 /// @returns a const `ast::Variable` constructed by calling Var() with the
810 /// arguments of `args`, which is automatically registered as a global
811 /// variable with the ast::Module.
812 template <typename... ARGS>
813 ast::Variable* GlobalConst(ARGS&&... args) {
814 auto* var = Const(std::forward<ARGS>(args)...);
815 AST().AddGlobalVariable(var);
816 return var;
817 }
818
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000819 /// @param func the function name
820 /// @param args the function call arguments
821 /// @returns a `ast::CallExpression` to the function `func`, with the
822 /// arguments of `args` converted to `ast::Expression`s using `Expr()`.
823 template <typename NAME, typename... ARGS>
824 ast::CallExpression* Call(NAME&& func, ARGS&&... args) {
825 return create<ast::CallExpression>(Expr(func),
826 ExprList(std::forward<ARGS>(args)...));
827 }
828
829 /// @param lhs the left hand argument to the addition operation
830 /// @param rhs the right hand argument to the addition operation
831 /// @returns a `ast::BinaryExpression` summing the arguments `lhs` and `rhs`
832 template <typename LHS, typename RHS>
833 ast::Expression* Add(LHS&& lhs, RHS&& rhs) {
834 return create<ast::BinaryExpression>(ast::BinaryOp::kAdd,
835 Expr(std::forward<LHS>(lhs)),
836 Expr(std::forward<RHS>(rhs)));
837 }
838
839 /// @param lhs the left hand argument to the subtraction operation
840 /// @param rhs the right hand argument to the subtraction operation
841 /// @returns a `ast::BinaryExpression` subtracting `rhs` from `lhs`
842 template <typename LHS, typename RHS>
843 ast::Expression* Sub(LHS&& lhs, RHS&& rhs) {
844 return create<ast::BinaryExpression>(ast::BinaryOp::kSubtract,
845 Expr(std::forward<LHS>(lhs)),
846 Expr(std::forward<RHS>(rhs)));
847 }
848
849 /// @param lhs the left hand argument to the multiplication operation
850 /// @param rhs the right hand argument to the multiplication operation
851 /// @returns a `ast::BinaryExpression` multiplying `rhs` from `lhs`
852 template <typename LHS, typename RHS>
853 ast::Expression* Mul(LHS&& lhs, RHS&& rhs) {
854 return create<ast::BinaryExpression>(ast::BinaryOp::kMultiply,
855 Expr(std::forward<LHS>(lhs)),
856 Expr(std::forward<RHS>(rhs)));
857 }
858
859 /// @param arr the array argument for the array accessor expression
860 /// @param idx the index argument for the array accessor expression
861 /// @returns a `ast::ArrayAccessorExpression` that indexes `arr` with `idx`
862 template <typename ARR, typename IDX>
863 ast::Expression* IndexAccessor(ARR&& arr, IDX&& idx) {
864 return create<ast::ArrayAccessorExpression>(Expr(std::forward<ARR>(arr)),
865 Expr(std::forward<IDX>(idx)));
866 }
867
868 /// @param obj the object for the member accessor expression
869 /// @param idx the index argument for the array accessor expression
870 /// @returns a `ast::MemberAccessorExpression` that indexes `obj` with `idx`
871 template <typename OBJ, typename IDX>
872 ast::Expression* MemberAccessor(OBJ&& obj, IDX&& idx) {
873 return create<ast::MemberAccessorExpression>(Expr(std::forward<OBJ>(obj)),
874 Expr(std::forward<IDX>(idx)));
875 }
876
Ben Clayton42d1e092021-02-02 14:29:15 +0000877 /// Creates a ast::StructMemberOffsetDecoration
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000878 /// @param val the offset value
879 /// @returns the offset decoration pointer
880 ast::StructMemberOffsetDecoration* MemberOffset(uint32_t val) {
881 return create<ast::StructMemberOffsetDecoration>(source_, val);
882 }
883
Ben Clayton42d1e092021-02-02 14:29:15 +0000884 /// Creates an ast::Function and registers it with the ast::Module.
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000885 /// @param source the source information
886 /// @param name the function name
887 /// @param params the function parameters
888 /// @param type the function return type
889 /// @param body the function body
890 /// @param decorations the function decorations
891 /// @returns the function pointer
892 ast::Function* Func(Source source,
893 std::string name,
894 ast::VariableList params,
895 type::Type* type,
896 ast::StatementList body,
897 ast::FunctionDecorationList decorations) {
Ben Clayton42d1e092021-02-02 14:29:15 +0000898 auto* func =
899 create<ast::Function>(source, Symbols().Register(name), params, type,
900 create<ast::BlockStatement>(body), decorations);
901 AST().Functions().Add(func);
902 return func;
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000903 }
904
Ben Clayton42d1e092021-02-02 14:29:15 +0000905 /// Creates an ast::Function and registers it with the ast::Module.
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000906 /// @param name the function name
907 /// @param params the function parameters
908 /// @param type the function return type
909 /// @param body the function body
910 /// @param decorations the function decorations
911 /// @returns the function pointer
912 ast::Function* Func(std::string name,
913 ast::VariableList params,
914 type::Type* type,
915 ast::StatementList body,
916 ast::FunctionDecorationList decorations) {
Ben Clayton42d1e092021-02-02 14:29:15 +0000917 auto* func =
918 create<ast::Function>(Symbols().Register(name), params, type,
919 create<ast::BlockStatement>(body), decorations);
920 AST().Functions().Add(func);
921 return func;
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000922 }
923
Ben Clayton42d1e092021-02-02 14:29:15 +0000924 /// Creates a ast::StructMember
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000925 /// @param source the source information
926 /// @param name the struct member name
927 /// @param type the struct member type
928 /// @returns the struct member pointer
929 ast::StructMember* Member(const Source& source,
930 const std::string& name,
931 type::Type* type) {
932 return create<ast::StructMember>(source, Symbols().Register(name), type,
933 ast::StructMemberDecorationList{});
934 }
935
Ben Clayton42d1e092021-02-02 14:29:15 +0000936 /// Creates a ast::StructMember
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000937 /// @param name the struct member name
938 /// @param type the struct member type
939 /// @returns the struct member pointer
940 ast::StructMember* Member(const std::string& name, type::Type* type) {
941 return create<ast::StructMember>(source_, Symbols().Register(name), type,
942 ast::StructMemberDecorationList{});
943 }
944
Ben Clayton42d1e092021-02-02 14:29:15 +0000945 /// Creates a ast::StructMember
Ben Claytona6b9a8e2021-01-26 16:57:10 +0000946 /// @param name the struct member name
947 /// @param type the struct member type
948 /// @param decorations the struct member decorations
949 /// @returns the struct member pointer
950 ast::StructMember* Member(const std::string& name,
951 type::Type* type,
952 ast::StructMemberDecorationList decorations) {
953 return create<ast::StructMember>(source_, Symbols().Register(name), type,
954 decorations);
955 }
956
957 /// Sets the current builder source to `src`
958 /// @param src the Source used for future create() calls
959 void SetSource(const Source& src) {
960 AssertNotMoved();
961 source_ = src;
962 }
963
964 /// Sets the current builder source to `loc`
965 /// @param loc the Source used for future create() calls
966 void SetSource(const Source::Location& loc) {
967 AssertNotMoved();
968 source_ = Source(loc);
969 }
970
Ben Clayton33352542021-01-29 16:43:41 +0000971 /// Helper for returning the resolved semantic type of the expression `expr`.
972 /// @note As the TypeDeterminator is run when the Program is built, this will
973 /// only be useful for the TypeDeterminer itself and tests that use their own
974 /// TypeDeterminer.
975 /// @param expr the AST expression
976 /// @return the resolved semantic type for the expression, or nullptr if the
977 /// expression has no resolved type.
978 type::Type* TypeOf(ast::Expression* expr) const;
979
Ben Clayton401b96b2021-02-03 17:19:59 +0000980 /// Wraps the ast::Expression in a statement. This is used by tests that
981 /// construct a partial AST and require the TypeDeterminer to reach these
982 /// nodes.
983 /// @param expr the ast::Expression to be wrapped by an ast::Statement
984 /// @return the ast::Statement that wraps the ast::Expression
985 ast::Statement* WrapInStatement(ast::Expression* expr);
986 /// Wraps the ast::Variable in a ast::VariableDeclStatement. This is used by
987 /// tests that construct a partial AST and require the TypeDeterminer to reach
988 /// these nodes.
989 /// @param v the ast::Variable to be wrapped by an ast::VariableDeclStatement
990 /// @return the ast::VariableDeclStatement that wraps the ast::Variable
991 ast::VariableDeclStatement* WrapInStatement(ast::Variable* v);
992 /// Returns the statement argument. Used as a passthrough-overload by
993 /// WrapInFunction().
994 /// @param stmt the ast::Statement
995 /// @return `stmt`
996 ast::Statement* WrapInStatement(ast::Statement* stmt);
997 /// Wraps the list of arguments in a simple function so that each is reachable
998 /// by the TypeDeterminer.
999 /// @param args a mix of ast::Expression, ast::Statement, ast::Variables.
1000 template <typename... ARGS>
1001 void WrapInFunction(ARGS&&... args) {
1002 ast::StatementList stmts{WrapInStatement(std::forward<ARGS>(args))...};
1003 WrapInFunction(stmts);
1004 }
1005 /// @param stmts a list of ast::Statement that will be wrapped by a function,
1006 /// so that each statement is reachable by the TypeDeterminer.
1007 void WrapInFunction(ast::StatementList stmts);
1008
Ben Claytona6b9a8e2021-01-26 16:57:10 +00001009 /// The builder types
1010 TypesBuilder ty;
1011
1012 protected:
1013 /// Asserts that the builder has not been moved.
1014 void AssertNotMoved() const;
1015
Ben Claytona6b9a8e2021-01-26 16:57:10 +00001016 private:
1017 type::Manager types_;
Ben Clayton7fdfff12021-01-29 15:17:30 +00001018 ASTNodeAllocator ast_nodes_;
1019 SemNodeAllocator sem_nodes_;
Ben Claytona6b9a8e2021-01-26 16:57:10 +00001020 ast::Module* ast_;
Ben Claytondd1b6fc2021-01-29 10:55:40 +00001021 semantic::Info sem_;
Ben Claytona6b9a8e2021-01-26 16:57:10 +00001022 SymbolTable symbols_;
Ben Clayton844217f2021-01-27 18:49:05 +00001023 diag::List diagnostics_;
Ben Claytona6b9a8e2021-01-26 16:57:10 +00001024
1025 /// The source to use when creating AST nodes without providing a Source as
1026 /// the first argument.
1027 Source source_;
1028
Ben Claytondd69ac32021-01-27 19:23:55 +00001029 /// Set by SetResolveOnBuild(). If set, the TypeDeterminer will be run on the
1030 /// program when built.
1031 bool resolve_on_build_ = true;
1032
Ben Claytona6b9a8e2021-01-26 16:57:10 +00001033 /// Set by MarkAsMoved(). Once set, no methods may be called on this builder.
1034 bool moved_ = false;
1035};
1036
1037//! @cond Doxygen_Suppress
1038// Various template specializations for ProgramBuilder::TypesBuilder::CToAST.
1039template <>
1040struct ProgramBuilder::TypesBuilder::CToAST<ProgramBuilder::i32> {
1041 static type::Type* get(const ProgramBuilder::TypesBuilder* t) {
1042 return t->i32();
1043 }
1044};
1045template <>
1046struct ProgramBuilder::TypesBuilder::CToAST<ProgramBuilder::u32> {
1047 static type::Type* get(const ProgramBuilder::TypesBuilder* t) {
1048 return t->u32();
1049 }
1050};
1051template <>
1052struct ProgramBuilder::TypesBuilder::CToAST<ProgramBuilder::f32> {
1053 static type::Type* get(const ProgramBuilder::TypesBuilder* t) {
1054 return t->f32();
1055 }
1056};
1057template <>
1058struct ProgramBuilder::TypesBuilder::CToAST<bool> {
1059 static type::Type* get(const ProgramBuilder::TypesBuilder* t) {
1060 return t->bool_();
1061 }
1062};
1063template <>
1064struct ProgramBuilder::TypesBuilder::CToAST<void> {
1065 static type::Type* get(const ProgramBuilder::TypesBuilder* t) {
1066 return t->void_();
1067 }
1068};
1069//! @endcond
1070
1071} // namespace tint
1072
1073#endif // SRC_PROGRAM_BUILDER_H_