1 // Copyright 2021 The Tint Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "src/program_builder.h"
16
17 #include "src/ast/assignment_statement.h"
18 #include "src/ast/call_statement.h"
19 #include "src/ast/variable_decl_statement.h"
20 #include "src/debug.h"
21 #include "src/demangler.h"
22 #include "src/sem/expression.h"
23 #include "src/sem/variable.h"
24
25 namespace tint {
26
27 ProgramBuilder::VarOptionals::~VarOptionals() = default;
28
ProgramBuilder()29 ProgramBuilder::ProgramBuilder()
30 : id_(ProgramID::New()),
31 ast_(ast_nodes_.Create<ast::Module>(id_, Source{})) {}
32
ProgramBuilder(ProgramBuilder && rhs)33 ProgramBuilder::ProgramBuilder(ProgramBuilder&& rhs)
34 : id_(std::move(rhs.id_)),
35 types_(std::move(rhs.types_)),
36 ast_nodes_(std::move(rhs.ast_nodes_)),
37 sem_nodes_(std::move(rhs.sem_nodes_)),
38 ast_(rhs.ast_),
39 sem_(std::move(rhs.sem_)),
40 symbols_(std::move(rhs.symbols_)),
41 diagnostics_(std::move(rhs.diagnostics_)),
42 transforms_applied_(std::move(rhs.transforms_applied_)) {
43 rhs.MarkAsMoved();
44 }
45
46 ProgramBuilder::~ProgramBuilder() = default;
47
operator =(ProgramBuilder && rhs)48 ProgramBuilder& ProgramBuilder::operator=(ProgramBuilder&& rhs) {
49 rhs.MarkAsMoved();
50 AssertNotMoved();
51 id_ = std::move(rhs.id_);
52 types_ = std::move(rhs.types_);
53 ast_nodes_ = std::move(rhs.ast_nodes_);
54 sem_nodes_ = std::move(rhs.sem_nodes_);
55 ast_ = rhs.ast_;
56 sem_ = std::move(rhs.sem_);
57 symbols_ = std::move(rhs.symbols_);
58 diagnostics_ = std::move(rhs.diagnostics_);
59 transforms_applied_ = std::move(rhs.transforms_applied_);
60 return *this;
61 }
62
Wrap(const Program * program)63 ProgramBuilder ProgramBuilder::Wrap(const Program* program) {
64 ProgramBuilder builder;
65 builder.id_ = program->ID();
66 builder.types_ = sem::Manager::Wrap(program->Types());
67 builder.ast_ = builder.create<ast::Module>(
68 program->AST().source, program->AST().GlobalDeclarations());
69 builder.sem_ = sem::Info::Wrap(program->Sem());
70 builder.symbols_ = program->Symbols();
71 builder.diagnostics_ = program->Diagnostics();
72 builder.transforms_applied_ = program->TransformsApplied();
73 return builder;
74 }
75
IsValid() const76 bool ProgramBuilder::IsValid() const {
77 return !diagnostics_.contains_errors();
78 }
79
MarkAsMoved()80 void ProgramBuilder::MarkAsMoved() {
81 AssertNotMoved();
82 moved_ = true;
83 }
84
AssertNotMoved() const85 void ProgramBuilder::AssertNotMoved() const {
86 if (moved_) {
87 TINT_ICE(ProgramBuilder, const_cast<ProgramBuilder*>(this)->diagnostics_)
88 << "Attempting to use ProgramBuilder after it has been moved";
89 }
90 }
91
TypeOf(const ast::Expression * expr) const92 const sem::Type* ProgramBuilder::TypeOf(const ast::Expression* expr) const {
93 auto* sem = Sem().Get(expr);
94 return sem ? sem->Type() : nullptr;
95 }
96
TypeOf(const ast::Variable * var) const97 const sem::Type* ProgramBuilder::TypeOf(const ast::Variable* var) const {
98 auto* sem = Sem().Get(var);
99 return sem ? sem->Type() : nullptr;
100 }
101
TypeOf(const ast::Type * type) const102 const sem::Type* ProgramBuilder::TypeOf(const ast::Type* type) const {
103 return Sem().Get(type);
104 }
105
TypeOf(const ast::TypeDecl * type_decl) const106 const sem::Type* ProgramBuilder::TypeOf(const ast::TypeDecl* type_decl) const {
107 return Sem().Get(type_decl);
108 }
109
Of(const ast::TypeDecl * decl) const110 const ast::TypeName* ProgramBuilder::TypesBuilder::Of(
111 const ast::TypeDecl* decl) const {
112 return type_name(decl->name);
113 }
114
TypesBuilder(ProgramBuilder * pb)115 ProgramBuilder::TypesBuilder::TypesBuilder(ProgramBuilder* pb) : builder(pb) {}
116
WrapInStatement(const ast::Expression * expr)117 const ast::Statement* ProgramBuilder::WrapInStatement(
118 const ast::Expression* expr) {
119 // Create a temporary variable of inferred type from expr.
120 return Decl(Const(symbols_.New(), nullptr, expr));
121 }
122
WrapInStatement(const ast::Variable * v)123 const ast::VariableDeclStatement* ProgramBuilder::WrapInStatement(
124 const ast::Variable* v) {
125 return create<ast::VariableDeclStatement>(v);
126 }
127
WrapInStatement(const ast::Statement * stmt)128 const ast::Statement* ProgramBuilder::WrapInStatement(
129 const ast::Statement* stmt) {
130 return stmt;
131 }
132
WrapInFunction(const ast::StatementList stmts)133 const ast::Function* ProgramBuilder::WrapInFunction(
134 const ast::StatementList stmts) {
135 return Func("test_function", {}, ty.void_(), std::move(stmts),
136 {create<ast::StageDecoration>(ast::PipelineStage::kCompute),
137 WorkgroupSize(1, 1, 1)});
138 }
139
140 } // namespace tint
141