Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 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/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 Clayton | 3fb9a3f | 2023-02-04 21:20:26 +0000 | [diff] [blame] | 22 | #include "src/tint/sem/value_expression.h" |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 23 | #include "src/tint/sem/variable.h" |
Ben Clayton | 884f952 | 2023-01-12 22:52:57 +0000 | [diff] [blame] | 24 | #include "src/tint/utils/compiler_macros.h" |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 25 | |
Ben Clayton | 0ce9ab0 | 2022-05-05 20:23:40 +0000 | [diff] [blame] | 26 | using namespace tint::number_suffixes; // NOLINT |
| 27 | |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 28 | namespace tint { |
| 29 | |
Ben Clayton | 58794ae | 2022-08-19 17:28:53 +0000 | [diff] [blame] | 30 | ProgramBuilder::VarOptions::~VarOptions() = default; |
| 31 | ProgramBuilder::LetOptions::~LetOptions() = default; |
| 32 | ProgramBuilder::ConstOptions::~ConstOptions() = default; |
| 33 | ProgramBuilder::OverrideOptions::~OverrideOptions() = default; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 34 | |
| 35 | ProgramBuilder::ProgramBuilder() |
Ben Clayton | 4a92a3c | 2022-07-18 20:50:02 +0000 | [diff] [blame] | 36 | : id_(ProgramID::New()), |
| 37 | ast_(ast_nodes_.Create<ast::Module>(id_, AllocateNodeID(), Source{})) {} |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 38 | |
| 39 | ProgramBuilder::ProgramBuilder(ProgramBuilder&& rhs) |
| 40 | : id_(std::move(rhs.id_)), |
Ben Clayton | 4a92a3c | 2022-07-18 20:50:02 +0000 | [diff] [blame] | 41 | last_ast_node_id_(std::move(rhs.last_ast_node_id_)), |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 42 | types_(std::move(rhs.types_)), |
| 43 | ast_nodes_(std::move(rhs.ast_nodes_)), |
| 44 | sem_nodes_(std::move(rhs.sem_nodes_)), |
Ben Clayton | 4a92a3c | 2022-07-18 20:50:02 +0000 | [diff] [blame] | 45 | ast_(std::move(rhs.ast_)), |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 46 | sem_(std::move(rhs.sem_)), |
| 47 | symbols_(std::move(rhs.symbols_)), |
| 48 | diagnostics_(std::move(rhs.diagnostics_)) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 49 | rhs.MarkAsMoved(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 50 | } |
| 51 | |
| 52 | ProgramBuilder::~ProgramBuilder() = default; |
| 53 | |
| 54 | ProgramBuilder& ProgramBuilder::operator=(ProgramBuilder&& rhs) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 55 | rhs.MarkAsMoved(); |
| 56 | AssertNotMoved(); |
| 57 | id_ = std::move(rhs.id_); |
Ben Clayton | 4a92a3c | 2022-07-18 20:50:02 +0000 | [diff] [blame] | 58 | last_ast_node_id_ = std::move(rhs.last_ast_node_id_); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 59 | types_ = std::move(rhs.types_); |
| 60 | ast_nodes_ = std::move(rhs.ast_nodes_); |
| 61 | sem_nodes_ = std::move(rhs.sem_nodes_); |
Ben Clayton | 4a92a3c | 2022-07-18 20:50:02 +0000 | [diff] [blame] | 62 | ast_ = std::move(rhs.ast_); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 63 | sem_ = std::move(rhs.sem_); |
| 64 | symbols_ = std::move(rhs.symbols_); |
| 65 | diagnostics_ = std::move(rhs.diagnostics_); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 66 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 67 | return *this; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 68 | } |
| 69 | |
| 70 | ProgramBuilder ProgramBuilder::Wrap(const Program* program) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 71 | ProgramBuilder builder; |
| 72 | builder.id_ = program->ID(); |
Ben Clayton | 4a92a3c | 2022-07-18 20:50:02 +0000 | [diff] [blame] | 73 | builder.last_ast_node_id_ = program->HighestASTNodeID(); |
dan sinclair | 837b804 | 2022-12-09 05:00:07 +0000 | [diff] [blame] | 74 | builder.types_ = type::Manager::Wrap(program->Types()); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 75 | 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 Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 81 | } |
| 82 | |
| 83 | bool ProgramBuilder::IsValid() const { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 84 | return !diagnostics_.contains_errors(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 85 | } |
| 86 | |
| 87 | void ProgramBuilder::MarkAsMoved() { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 88 | AssertNotMoved(); |
| 89 | moved_ = true; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 90 | } |
| 91 | |
| 92 | void ProgramBuilder::AssertNotMoved() const { |
Ben Clayton | 884f952 | 2023-01-12 22:52:57 +0000 | [diff] [blame] | 93 | if (TINT_UNLIKELY(moved_)) { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 94 | TINT_ICE(ProgramBuilder, const_cast<ProgramBuilder*>(this)->diagnostics_) |
| 95 | << "Attempting to use ProgramBuilder after it has been moved"; |
| 96 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 97 | } |
| 98 | |
dan sinclair | 5f764d8 | 2022-12-08 00:32:27 +0000 | [diff] [blame] | 99 | const type::Type* ProgramBuilder::TypeOf(const ast::Expression* expr) const { |
Ben Clayton | 0b4a2f1 | 2023-02-05 22:59:40 +0000 | [diff] [blame] | 100 | auto* sem = Sem().GetVal(expr); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 101 | return sem ? sem->Type() : nullptr; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 102 | } |
| 103 | |
dan sinclair | 5f764d8 | 2022-12-08 00:32:27 +0000 | [diff] [blame] | 104 | const type::Type* ProgramBuilder::TypeOf(const ast::Variable* var) const { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 105 | auto* sem = Sem().Get(var); |
| 106 | return sem ? sem->Type() : nullptr; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 107 | } |
| 108 | |
dan sinclair | 5f764d8 | 2022-12-08 00:32:27 +0000 | [diff] [blame] | 109 | const type::Type* ProgramBuilder::TypeOf(const ast::Type* type) const { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 110 | return Sem().Get(type); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 111 | } |
| 112 | |
dan sinclair | 5f764d8 | 2022-12-08 00:32:27 +0000 | [diff] [blame] | 113 | const type::Type* ProgramBuilder::TypeOf(const ast::TypeDecl* type_decl) const { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 114 | return Sem().Get(type_decl); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 115 | } |
| 116 | |
Ben Clayton | d7d7188 | 2022-09-05 20:51:23 +0000 | [diff] [blame] | 117 | std::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 sinclair | 5f764d8 | 2022-12-08 00:32:27 +0000 | [diff] [blame] | 122 | std::string ProgramBuilder::FriendlyName(const type::Type* type) const { |
Ben Clayton | d7d7188 | 2022-09-05 20:51:23 +0000 | [diff] [blame] | 123 | return type ? type->FriendlyName(Symbols()) : "<null>"; |
| 124 | } |
| 125 | |
| 126 | std::string ProgramBuilder::FriendlyName(std::nullptr_t) const { |
| 127 | return "<null>"; |
| 128 | } |
| 129 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 130 | const ast::TypeName* ProgramBuilder::TypesBuilder::Of(const ast::TypeDecl* decl) const { |
Ben Clayton | b75252b | 2023-02-09 10:34:14 +0000 | [diff] [blame] | 131 | return (*this)(decl->name->symbol); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 132 | } |
| 133 | |
| 134 | ProgramBuilder::TypesBuilder::TypesBuilder(ProgramBuilder* pb) : builder(pb) {} |
| 135 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 136 | const ast::Statement* ProgramBuilder::WrapInStatement(const ast::Expression* expr) { |
| 137 | // Create a temporary variable of inferred type from expr. |
Ben Clayton | 58794ae | 2022-08-19 17:28:53 +0000 | [diff] [blame] | 138 | return Decl(Let(symbols_.New(), expr)); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 139 | } |
| 140 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 141 | const ast::VariableDeclStatement* ProgramBuilder::WrapInStatement(const ast::Variable* v) { |
| 142 | return create<ast::VariableDeclStatement>(v); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 143 | } |
| 144 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 145 | const ast::Statement* ProgramBuilder::WrapInStatement(const ast::Statement* stmt) { |
| 146 | return stmt; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 147 | } |
| 148 | |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 149 | const ast::Function* ProgramBuilder::WrapInFunction(utils::VectorRef<const ast::Statement*> stmts) { |
Ben Clayton | 7164b97 | 2022-06-15 10:02:37 +0000 | [diff] [blame] | 150 | return Func("test_function", {}, ty.void_(), std::move(stmts), |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 151 | utils::Vector{ |
Ben Clayton | 7164b97 | 2022-06-15 10:02:37 +0000 | [diff] [blame] | 152 | create<ast::StageAttribute>(ast::PipelineStage::kCompute), |
| 153 | WorkgroupSize(1_i, 1_i, 1_i), |
| 154 | }); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 155 | } |
| 156 | |
dan sinclair | cf58122 | 2023-01-03 20:25:37 +0000 | [diff] [blame] | 157 | const 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 Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 192 | } // namespace tint |