blob: a847e00a48492f17742dba8b68bdca9d0343bf9c [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#include "src/tint/program_builder.h"
16
17#include "src/tint/ast/assignment_statement.h"
18#include "src/tint/ast/call_statement.h"
19#include "src/tint/ast/variable_decl_statement.h"
20#include "src/tint/debug.h"
21#include "src/tint/demangler.h"
Ben Clayton3fb9a3f2023-02-04 21:20:26 +000022#include "src/tint/sem/value_expression.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000023#include "src/tint/sem/variable.h"
Ben Clayton884f9522023-01-12 22:52:57 +000024#include "src/tint/utils/compiler_macros.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000025
Ben Clayton0ce9ab02022-05-05 20:23:40 +000026using namespace tint::number_suffixes; // NOLINT
27
Ryan Harrisondbc13af2022-02-21 15:19:07 +000028namespace tint {
29
Ben Clayton58794ae2022-08-19 17:28:53 +000030ProgramBuilder::VarOptions::~VarOptions() = default;
31ProgramBuilder::LetOptions::~LetOptions() = default;
32ProgramBuilder::ConstOptions::~ConstOptions() = default;
33ProgramBuilder::OverrideOptions::~OverrideOptions() = default;
Ryan Harrisondbc13af2022-02-21 15:19:07 +000034
35ProgramBuilder::ProgramBuilder()
Ben Clayton4a92a3c2022-07-18 20:50:02 +000036 : id_(ProgramID::New()),
37 ast_(ast_nodes_.Create<ast::Module>(id_, AllocateNodeID(), Source{})) {}
Ryan Harrisondbc13af2022-02-21 15:19:07 +000038
39ProgramBuilder::ProgramBuilder(ProgramBuilder&& rhs)
40 : id_(std::move(rhs.id_)),
Ben Clayton4a92a3c2022-07-18 20:50:02 +000041 last_ast_node_id_(std::move(rhs.last_ast_node_id_)),
Ryan Harrisondbc13af2022-02-21 15:19:07 +000042 types_(std::move(rhs.types_)),
43 ast_nodes_(std::move(rhs.ast_nodes_)),
44 sem_nodes_(std::move(rhs.sem_nodes_)),
Ben Clayton4a92a3c2022-07-18 20:50:02 +000045 ast_(std::move(rhs.ast_)),
Ryan Harrisondbc13af2022-02-21 15:19:07 +000046 sem_(std::move(rhs.sem_)),
47 symbols_(std::move(rhs.symbols_)),
48 diagnostics_(std::move(rhs.diagnostics_)) {
dan sinclair41e4d9a2022-05-01 14:40:55 +000049 rhs.MarkAsMoved();
Ryan Harrisondbc13af2022-02-21 15:19:07 +000050}
51
52ProgramBuilder::~ProgramBuilder() = default;
53
54ProgramBuilder& ProgramBuilder::operator=(ProgramBuilder&& rhs) {
dan sinclair41e4d9a2022-05-01 14:40:55 +000055 rhs.MarkAsMoved();
56 AssertNotMoved();
57 id_ = std::move(rhs.id_);
Ben Clayton4a92a3c2022-07-18 20:50:02 +000058 last_ast_node_id_ = std::move(rhs.last_ast_node_id_);
dan sinclair41e4d9a2022-05-01 14:40:55 +000059 types_ = std::move(rhs.types_);
60 ast_nodes_ = std::move(rhs.ast_nodes_);
61 sem_nodes_ = std::move(rhs.sem_nodes_);
Ben Clayton4a92a3c2022-07-18 20:50:02 +000062 ast_ = std::move(rhs.ast_);
dan sinclair41e4d9a2022-05-01 14:40:55 +000063 sem_ = std::move(rhs.sem_);
64 symbols_ = std::move(rhs.symbols_);
65 diagnostics_ = std::move(rhs.diagnostics_);
Ryan Harrisondbc13af2022-02-21 15:19:07 +000066
dan sinclair41e4d9a2022-05-01 14:40:55 +000067 return *this;
Ryan Harrisondbc13af2022-02-21 15:19:07 +000068}
69
70ProgramBuilder ProgramBuilder::Wrap(const Program* program) {
dan sinclair41e4d9a2022-05-01 14:40:55 +000071 ProgramBuilder builder;
72 builder.id_ = program->ID();
Ben Clayton4a92a3c2022-07-18 20:50:02 +000073 builder.last_ast_node_id_ = program->HighestASTNodeID();
dan sinclair837b8042022-12-09 05:00:07 +000074 builder.types_ = type::Manager::Wrap(program->Types());
dan sinclair41e4d9a2022-05-01 14:40:55 +000075 builder.ast_ =
76 builder.create<ast::Module>(program->AST().source, program->AST().GlobalDeclarations());
77 builder.sem_ = sem::Info::Wrap(program->Sem());
78 builder.symbols_ = program->Symbols();
79 builder.diagnostics_ = program->Diagnostics();
80 return builder;
Ryan Harrisondbc13af2022-02-21 15:19:07 +000081}
82
83bool ProgramBuilder::IsValid() const {
dan sinclair41e4d9a2022-05-01 14:40:55 +000084 return !diagnostics_.contains_errors();
Ryan Harrisondbc13af2022-02-21 15:19:07 +000085}
86
87void ProgramBuilder::MarkAsMoved() {
dan sinclair41e4d9a2022-05-01 14:40:55 +000088 AssertNotMoved();
89 moved_ = true;
Ryan Harrisondbc13af2022-02-21 15:19:07 +000090}
91
92void ProgramBuilder::AssertNotMoved() const {
Ben Clayton884f9522023-01-12 22:52:57 +000093 if (TINT_UNLIKELY(moved_)) {
dan sinclair41e4d9a2022-05-01 14:40:55 +000094 TINT_ICE(ProgramBuilder, const_cast<ProgramBuilder*>(this)->diagnostics_)
95 << "Attempting to use ProgramBuilder after it has been moved";
96 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +000097}
98
dan sinclair5f764d82022-12-08 00:32:27 +000099const type::Type* ProgramBuilder::TypeOf(const ast::Expression* expr) const {
Ben Clayton0b4a2f12023-02-05 22:59:40 +0000100 auto* sem = Sem().GetVal(expr);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000101 return sem ? sem->Type() : nullptr;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000102}
103
dan sinclair5f764d82022-12-08 00:32:27 +0000104const type::Type* ProgramBuilder::TypeOf(const ast::Variable* var) const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000105 auto* sem = Sem().Get(var);
106 return sem ? sem->Type() : nullptr;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000107}
108
dan sinclair5f764d82022-12-08 00:32:27 +0000109const type::Type* ProgramBuilder::TypeOf(const ast::Type* type) const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000110 return Sem().Get(type);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000111}
112
dan sinclair5f764d82022-12-08 00:32:27 +0000113const type::Type* ProgramBuilder::TypeOf(const ast::TypeDecl* type_decl) const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000114 return Sem().Get(type_decl);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000115}
116
Ben Claytond7d71882022-09-05 20:51:23 +0000117std::string ProgramBuilder::FriendlyName(const ast::Type* type) const {
118 TINT_ASSERT_PROGRAM_IDS_EQUAL(ProgramBuilder, type, ID());
119 return type ? type->FriendlyName(Symbols()) : "<null>";
120}
121
dan sinclair5f764d82022-12-08 00:32:27 +0000122std::string ProgramBuilder::FriendlyName(const type::Type* type) const {
Ben Claytond7d71882022-09-05 20:51:23 +0000123 return type ? type->FriendlyName(Symbols()) : "<null>";
124}
125
126std::string ProgramBuilder::FriendlyName(std::nullptr_t) const {
127 return "<null>";
128}
129
dan sinclair41e4d9a2022-05-01 14:40:55 +0000130const ast::TypeName* ProgramBuilder::TypesBuilder::Of(const ast::TypeDecl* decl) const {
Ben Claytonb75252b2023-02-09 10:34:14 +0000131 return (*this)(decl->name->symbol);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000132}
133
134ProgramBuilder::TypesBuilder::TypesBuilder(ProgramBuilder* pb) : builder(pb) {}
135
dan sinclair41e4d9a2022-05-01 14:40:55 +0000136const ast::Statement* ProgramBuilder::WrapInStatement(const ast::Expression* expr) {
137 // Create a temporary variable of inferred type from expr.
Ben Clayton58794ae2022-08-19 17:28:53 +0000138 return Decl(Let(symbols_.New(), expr));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000139}
140
dan sinclair41e4d9a2022-05-01 14:40:55 +0000141const ast::VariableDeclStatement* ProgramBuilder::WrapInStatement(const ast::Variable* v) {
142 return create<ast::VariableDeclStatement>(v);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000143}
144
dan sinclair41e4d9a2022-05-01 14:40:55 +0000145const ast::Statement* ProgramBuilder::WrapInStatement(const ast::Statement* stmt) {
146 return stmt;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000147}
148
Ben Clayton783b1692022-08-02 17:03:35 +0000149const ast::Function* ProgramBuilder::WrapInFunction(utils::VectorRef<const ast::Statement*> stmts) {
Ben Clayton7164b972022-06-15 10:02:37 +0000150 return Func("test_function", {}, ty.void_(), std::move(stmts),
Ben Clayton783b1692022-08-02 17:03:35 +0000151 utils::Vector{
Ben Clayton7164b972022-06-15 10:02:37 +0000152 create<ast::StageAttribute>(ast::PipelineStage::kCompute),
153 WorkgroupSize(1_i, 1_i, 1_i),
154 });
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000155}
156
dan sinclaircf581222023-01-03 20:25:37 +0000157const constant::Value* ProgramBuilder::createSplatOrComposite(
158 const type::Type* type,
159 utils::VectorRef<const constant::Value*> elements) {
160 if (elements.IsEmpty()) {
161 return nullptr;
162 }
163
164 bool any_zero = false;
165 bool all_zero = true;
166 bool all_equal = true;
167 auto* first = elements.Front();
168 for (auto* el : elements) {
169 if (!el) {
170 return nullptr;
171 }
172 if (!any_zero && el->AnyZero()) {
173 any_zero = true;
174 }
175 if (all_zero && !el->AllZero()) {
176 all_zero = false;
177 }
178 if (all_equal && el != first) {
179 if (!el->Equal(first)) {
180 all_equal = false;
181 }
182 }
183 }
184 if (all_equal) {
185 return create<constant::Splat>(type, elements[0], elements.Length());
186 }
187
188 return constant_nodes_.Create<constant::Composite>(type, std::move(elements), all_zero,
189 any_zero);
190}
191
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000192} // namespace tint