blob: a1cf5c8b47fe8fb74cd4c17ede09a5d1dde66dcd [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.h"
16
17#include <utility>
18
Ryan Harrisondbc13af2022-02-21 15:19:07 +000019#include "src/tint/resolver/resolver.h"
Ben Clayton971318f2023-02-14 13:52:43 +000020#include "src/tint/sem/type_expression.h"
Ben Clayton3fb9a3f2023-02-04 21:20:26 +000021#include "src/tint/sem/value_expression.h"
Ben Clayton23946b32023-03-09 16:50:19 +000022#include "src/tint/switch.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000023
24namespace tint {
25namespace {
26
27std::string DefaultPrinter(const Program*) {
dan sinclair41e4d9a2022-05-01 14:40:55 +000028 return "<no program printer assigned>";
Ryan Harrisondbc13af2022-02-21 15:19:07 +000029}
30
31} // namespace
32
33Program::Printer Program::printer = DefaultPrinter;
34
35Program::Program() = default;
36
37Program::Program(Program&& program)
38 : id_(std::move(program.id_)),
Ben Clayton4a92a3c2022-07-18 20:50:02 +000039 highest_node_id_(std::move(program.highest_node_id_)),
Ryan Harrisondbc13af2022-02-21 15:19:07 +000040 types_(std::move(program.types_)),
41 ast_nodes_(std::move(program.ast_nodes_)),
42 sem_nodes_(std::move(program.sem_nodes_)),
Ben Claytonaa037ac2022-06-29 19:07:30 +000043 constant_nodes_(std::move(program.constant_nodes_)),
Ryan Harrisondbc13af2022-02-21 15:19:07 +000044 ast_(std::move(program.ast_)),
45 sem_(std::move(program.sem_)),
46 symbols_(std::move(program.symbols_)),
47 diagnostics_(std::move(program.diagnostics_)),
48 is_valid_(program.is_valid_) {
dan sinclair41e4d9a2022-05-01 14:40:55 +000049 program.AssertNotMoved();
50 program.moved_ = true;
Ryan Harrisondbc13af2022-02-21 15:19:07 +000051}
52
53Program::Program(ProgramBuilder&& builder) {
dan sinclair41e4d9a2022-05-01 14:40:55 +000054 id_ = builder.ID();
Ben Clayton4a92a3c2022-07-18 20:50:02 +000055 highest_node_id_ = builder.LastAllocatedNodeID();
Ryan Harrisondbc13af2022-02-21 15:19:07 +000056
dan sinclair41e4d9a2022-05-01 14:40:55 +000057 is_valid_ = builder.IsValid();
58 if (builder.ResolveOnBuild() && builder.IsValid()) {
59 resolver::Resolver resolver(&builder);
60 if (!resolver.Resolve()) {
61 is_valid_ = false;
62 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +000063 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +000064
dan sinclair41e4d9a2022-05-01 14:40:55 +000065 // The above must be called *before* the calls to std::move() below
66 types_ = std::move(builder.Types());
67 ast_nodes_ = std::move(builder.ASTNodes());
68 sem_nodes_ = std::move(builder.SemNodes());
Ben Claytonaa037ac2022-06-29 19:07:30 +000069 constant_nodes_ = std::move(builder.ConstantNodes());
dan sinclair41e4d9a2022-05-01 14:40:55 +000070 ast_ = &builder.AST(); // ast::Module is actually a heap allocation.
71 sem_ = std::move(builder.Sem());
72 symbols_ = std::move(builder.Symbols());
73 diagnostics_.add(std::move(builder.Diagnostics()));
74 builder.MarkAsMoved();
Ryan Harrisondbc13af2022-02-21 15:19:07 +000075
dan sinclair41e4d9a2022-05-01 14:40:55 +000076 if (!is_valid_ && !diagnostics_.contains_errors()) {
77 // If the builder claims to be invalid, then we really should have an error
78 // message generated. If we find a situation where the program is not valid
79 // and there are no errors reported, add one here.
80 diagnostics_.add_error(diag::System::Program, "invalid program generated");
81 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +000082}
83
84Program::~Program() = default;
85
86Program& Program::operator=(Program&& program) {
dan sinclair41e4d9a2022-05-01 14:40:55 +000087 program.AssertNotMoved();
88 program.moved_ = true;
89 moved_ = false;
90 id_ = std::move(program.id_);
Ben Clayton4a92a3c2022-07-18 20:50:02 +000091 highest_node_id_ = std::move(program.highest_node_id_);
dan sinclair41e4d9a2022-05-01 14:40:55 +000092 types_ = std::move(program.types_);
93 ast_nodes_ = std::move(program.ast_nodes_);
94 sem_nodes_ = std::move(program.sem_nodes_);
Ben Claytonaa037ac2022-06-29 19:07:30 +000095 constant_nodes_ = std::move(program.constant_nodes_);
dan sinclair41e4d9a2022-05-01 14:40:55 +000096 ast_ = std::move(program.ast_);
97 sem_ = std::move(program.sem_);
98 symbols_ = std::move(program.symbols_);
99 diagnostics_ = std::move(program.diagnostics_);
100 is_valid_ = program.is_valid_;
101 return *this;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000102}
103
104Program Program::Clone() const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000105 AssertNotMoved();
106 return Program(CloneAsBuilder());
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000107}
108
109ProgramBuilder Program::CloneAsBuilder() const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000110 AssertNotMoved();
111 ProgramBuilder out;
112 CloneContext(&out, this).Clone();
113 return out;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000114}
115
116bool Program::IsValid() const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000117 AssertNotMoved();
118 return is_valid_;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000119}
120
dan sinclair5f764d82022-12-08 00:32:27 +0000121const type::Type* Program::TypeOf(const ast::Expression* expr) const {
Ben Clayton971318f2023-02-14 13:52:43 +0000122 return tint::Switch(
123 Sem().Get(expr), //
124 [](const sem::ValueExpression* ty_expr) { return ty_expr->Type(); },
125 [](const sem::TypeExpression* ty_expr) { return ty_expr->Type(); });
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000126}
127
Ben Clayton971318f2023-02-14 13:52:43 +0000128const type::Type* Program::TypeOf(const ast::Variable* var) const {
129 auto* sem = Sem().Get(var);
130 return sem ? sem->Type() : nullptr;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000131}
132
dan sinclair5f764d82022-12-08 00:32:27 +0000133const type::Type* Program::TypeOf(const ast::TypeDecl* type_decl) const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000134 return Sem().Get(type_decl);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000135}
136
137void Program::AssertNotMoved() const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000138 TINT_ASSERT(Program, !moved_);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000139}
140
141} // namespace tint