| // Copyright 2021 The Tint Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "src/program_builder.h" |
| |
| #include "src/ast/assignment_statement.h" |
| #include "src/ast/call_statement.h" |
| #include "src/ast/variable_decl_statement.h" |
| #include "src/debug.h" |
| #include "src/demangler.h" |
| #include "src/sem/expression.h" |
| |
| namespace tint { |
| |
| ProgramBuilder::ProgramBuilder() |
| : id_(ProgramID::New()), |
| ast_(ast_nodes_.Create<ast::Module>(id_, Source{})) {} |
| |
| ProgramBuilder::ProgramBuilder(ProgramBuilder&& rhs) |
| : id_(std::move(rhs.id_)), |
| types_(std::move(rhs.types_)), |
| ast_nodes_(std::move(rhs.ast_nodes_)), |
| sem_nodes_(std::move(rhs.sem_nodes_)), |
| ast_(rhs.ast_), |
| sem_(std::move(rhs.sem_)), |
| symbols_(std::move(rhs.symbols_)) { |
| rhs.MarkAsMoved(); |
| } |
| |
| ProgramBuilder::~ProgramBuilder() = default; |
| |
| ProgramBuilder& ProgramBuilder::operator=(ProgramBuilder&& rhs) { |
| rhs.MarkAsMoved(); |
| AssertNotMoved(); |
| id_ = std::move(rhs.id_); |
| types_ = std::move(rhs.types_); |
| ast_nodes_ = std::move(rhs.ast_nodes_); |
| sem_nodes_ = std::move(rhs.sem_nodes_); |
| ast_ = rhs.ast_; |
| sem_ = std::move(rhs.sem_); |
| symbols_ = std::move(rhs.symbols_); |
| return *this; |
| } |
| |
| ProgramBuilder ProgramBuilder::Wrap(const Program* program) { |
| ProgramBuilder builder; |
| builder.id_ = program->ID(); |
| builder.types_ = type::Manager::Wrap(program->Types()); |
| builder.ast_ = builder.create<ast::Module>( |
| program->AST().source(), program->AST().GlobalDeclarations()); |
| builder.sem_ = sem::Info::Wrap(program->Sem()); |
| builder.symbols_ = program->Symbols(); |
| builder.diagnostics_ = program->Diagnostics(); |
| return builder; |
| } |
| |
| bool ProgramBuilder::IsValid() const { |
| return !diagnostics_.contains_errors(); |
| } |
| |
| std::string ProgramBuilder::str(const ast::Node* node) const { |
| return Demangler().Demangle(Symbols(), node->str(Sem())); |
| } |
| |
| void ProgramBuilder::MarkAsMoved() { |
| AssertNotMoved(); |
| moved_ = true; |
| } |
| |
| void ProgramBuilder::AssertNotMoved() const { |
| if (moved_) { |
| TINT_ICE(const_cast<ProgramBuilder*>(this)->Diagnostics()) |
| << "Attempting to use ProgramBuilder after it has been moved"; |
| } |
| } |
| |
| type::Type* ProgramBuilder::TypeOf(ast::Expression* expr) const { |
| auto* sem = Sem().Get(expr); |
| return sem ? sem->Type() : nullptr; |
| } |
| |
| ast::ConstructorExpression* ProgramBuilder::ConstructValueFilledWith( |
| type::Type* type, |
| int elem_value) { |
| auto* unwrapped_type = type->UnwrapAliasIfNeeded(); |
| if (unwrapped_type->Is<type::Bool>()) { |
| return create<ast::ScalarConstructorExpression>( |
| create<ast::BoolLiteral>(type, elem_value == 0 ? false : true)); |
| } |
| if (unwrapped_type->Is<type::I32>()) { |
| return create<ast::ScalarConstructorExpression>(create<ast::SintLiteral>( |
| type, static_cast<ProgramBuilder::i32>(elem_value))); |
| } |
| if (unwrapped_type->Is<type::U32>()) { |
| return create<ast::ScalarConstructorExpression>(create<ast::UintLiteral>( |
| type, static_cast<ProgramBuilder::u32>(elem_value))); |
| } |
| if (unwrapped_type->Is<type::F32>()) { |
| return create<ast::ScalarConstructorExpression>(create<ast::FloatLiteral>( |
| type, static_cast<ProgramBuilder::f32>(elem_value))); |
| } |
| if (auto* v = unwrapped_type->As<type::Vector>()) { |
| ast::ExpressionList el(v->size()); |
| for (size_t i = 0; i < el.size(); i++) { |
| el[i] = ConstructValueFilledWith(v->type(), elem_value); |
| } |
| return create<ast::TypeConstructorExpression>(type, std::move(el)); |
| } |
| if (auto* m = unwrapped_type->As<type::Matrix>()) { |
| auto* col_vec_type = create<type::Vector>(m->type(), m->rows()); |
| ast::ExpressionList el(col_vec_type->size()); |
| for (size_t i = 0; i < el.size(); i++) { |
| el[i] = ConstructValueFilledWith(col_vec_type, elem_value); |
| } |
| return create<ast::TypeConstructorExpression>(type, std::move(el)); |
| } |
| TINT_ASSERT(false); |
| return nullptr; |
| } |
| |
| ProgramBuilder::TypesBuilder::TypesBuilder(ProgramBuilder* pb) : builder(pb) {} |
| |
| ast::Statement* ProgramBuilder::WrapInStatement(ast::Literal* lit) { |
| return WrapInStatement(create<ast::ScalarConstructorExpression>(lit)); |
| } |
| |
| ast::Statement* ProgramBuilder::WrapInStatement(ast::Expression* expr) { |
| // Create a temporary variable of inferred type from expr. |
| return Decl(Var(symbols_.New(), nullptr, ast::StorageClass::kFunction, expr)); |
| } |
| |
| ast::VariableDeclStatement* ProgramBuilder::WrapInStatement(ast::Variable* v) { |
| return create<ast::VariableDeclStatement>(v); |
| } |
| |
| ast::Statement* ProgramBuilder::WrapInStatement(ast::Statement* stmt) { |
| return stmt; |
| } |
| |
| ast::Function* ProgramBuilder::WrapInFunction(ast::StatementList stmts) { |
| return Func("test_function", {}, ty.void_(), std::move(stmts), |
| {create<ast::StageDecoration>(ast::PipelineStage::kCompute)}); |
| } |
| |
| } // namespace tint |