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.h"
16
17 #include <utility>
18
19 #include "src/demangler.h"
20 #include "src/resolver/resolver.h"
21 #include "src/sem/expression.h"
22
23 namespace tint {
24 namespace {
25
DefaultPrinter(const Program *)26 std::string DefaultPrinter(const Program*) {
27 return "<no program printer assigned>";
28 }
29
30 } // namespace
31
32 Program::Printer Program::printer = DefaultPrinter;
33
34 Program::Program() = default;
35
Program(Program && program)36 Program::Program(Program&& program)
37 : id_(std::move(program.id_)),
38 types_(std::move(program.types_)),
39 ast_nodes_(std::move(program.ast_nodes_)),
40 sem_nodes_(std::move(program.sem_nodes_)),
41 ast_(std::move(program.ast_)),
42 sem_(std::move(program.sem_)),
43 symbols_(std::move(program.symbols_)),
44 diagnostics_(std::move(program.diagnostics_)),
45 transforms_applied_(std::move(program.transforms_applied_)),
46 is_valid_(program.is_valid_) {
47 program.AssertNotMoved();
48 program.moved_ = true;
49 }
50
Program(ProgramBuilder && builder)51 Program::Program(ProgramBuilder&& builder) {
52 id_ = builder.ID();
53
54 is_valid_ = builder.IsValid();
55 if (builder.ResolveOnBuild() && builder.IsValid()) {
56 resolver::Resolver resolver(&builder);
57 if (!resolver.Resolve()) {
58 is_valid_ = false;
59 }
60 }
61
62 // The above must be called *before* the calls to std::move() below
63 types_ = std::move(builder.Types());
64 ast_nodes_ = std::move(builder.ASTNodes());
65 sem_nodes_ = std::move(builder.SemNodes());
66 ast_ = &builder.AST(); // ast::Module is actually a heap allocation.
67 sem_ = std::move(builder.Sem());
68 symbols_ = std::move(builder.Symbols());
69 diagnostics_.add(std::move(builder.Diagnostics()));
70 transforms_applied_ = builder.TransformsApplied();
71 builder.MarkAsMoved();
72
73 if (!is_valid_ && !diagnostics_.contains_errors()) {
74 // If the builder claims to be invalid, then we really should have an error
75 // message generated. If we find a situation where the program is not valid
76 // and there are no errors reported, add one here.
77 diagnostics_.add_error(diag::System::Program, "invalid program generated");
78 }
79 }
80
81 Program::~Program() = default;
82
operator =(Program && program)83 Program& Program::operator=(Program&& program) {
84 program.AssertNotMoved();
85 program.moved_ = true;
86 moved_ = false;
87 id_ = std::move(program.id_);
88 types_ = std::move(program.types_);
89 ast_nodes_ = std::move(program.ast_nodes_);
90 sem_nodes_ = std::move(program.sem_nodes_);
91 ast_ = std::move(program.ast_);
92 sem_ = std::move(program.sem_);
93 symbols_ = std::move(program.symbols_);
94 diagnostics_ = std::move(program.diagnostics_);
95 transforms_applied_ = std::move(program.transforms_applied_);
96 is_valid_ = program.is_valid_;
97 return *this;
98 }
99
Clone() const100 Program Program::Clone() const {
101 AssertNotMoved();
102 return Program(CloneAsBuilder());
103 }
104
CloneAsBuilder() const105 ProgramBuilder Program::CloneAsBuilder() const {
106 AssertNotMoved();
107 ProgramBuilder out;
108 CloneContext(&out, this).Clone();
109 return out;
110 }
111
IsValid() const112 bool Program::IsValid() const {
113 AssertNotMoved();
114 return is_valid_;
115 }
116
TypeOf(const ast::Expression * expr) const117 const sem::Type* Program::TypeOf(const ast::Expression* expr) const {
118 auto* sem = Sem().Get(expr);
119 return sem ? sem->Type() : nullptr;
120 }
121
TypeOf(const ast::Type * type) const122 const sem::Type* Program::TypeOf(const ast::Type* type) const {
123 return Sem().Get(type);
124 }
125
TypeOf(const ast::TypeDecl * type_decl) const126 const sem::Type* Program::TypeOf(const ast::TypeDecl* type_decl) const {
127 return Sem().Get(type_decl);
128 }
129
AssertNotMoved() const130 void Program::AssertNotMoved() const {
131 TINT_ASSERT(Program, !moved_);
132 }
133
134 } // namespace tint
135