1 // Copyright 2019 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/torque/torque-compiler.h"
6
7 #include <fstream>
8 #include "src/torque/declarable.h"
9 #include "src/torque/declaration-visitor.h"
10 #include "src/torque/global-context.h"
11 #include "src/torque/implementation-visitor.h"
12 #include "src/torque/torque-parser.h"
13 #include "src/torque/type-oracle.h"
14
15 namespace v8 {
16 namespace internal {
17 namespace torque {
18
19 namespace {
20
ReadFile(const std::string & path)21 base::Optional<std::string> ReadFile(const std::string& path) {
22 std::ifstream file_stream(path);
23 if (!file_stream.good()) return base::nullopt;
24
25 return std::string{std::istreambuf_iterator<char>(file_stream),
26 std::istreambuf_iterator<char>()};
27 }
28
ReadAndParseTorqueFile(const std::string & path)29 void ReadAndParseTorqueFile(const std::string& path) {
30 SourceId source_id = SourceFileMap::AddSource(path);
31 CurrentSourceFile::Scope source_id_scope(source_id);
32
33 // path might be either a normal file path or an encoded URI.
34 auto maybe_content = ReadFile(SourceFileMap::AbsolutePath(source_id));
35 if (!maybe_content) {
36 if (auto maybe_path = FileUriDecode(path)) {
37 maybe_content = ReadFile(*maybe_path);
38 }
39 }
40
41 if (!maybe_content) {
42 Error("Cannot open file path/uri: ", path).Throw();
43 }
44
45 ParseTorque(*maybe_content);
46 }
47
CompileCurrentAst(TorqueCompilerOptions options)48 void CompileCurrentAst(TorqueCompilerOptions options) {
49 GlobalContext::Scope global_context(std::move(CurrentAst::Get()));
50 if (options.collect_language_server_data) {
51 GlobalContext::SetCollectLanguageServerData();
52 }
53 if (options.collect_kythe_data) {
54 GlobalContext::SetCollectKytheData();
55 }
56 if (options.force_assert_statements) {
57 GlobalContext::SetForceAssertStatements();
58 }
59 if (options.annotate_ir) {
60 GlobalContext::SetAnnotateIR();
61 }
62 TargetArchitecture::Scope target_architecture(options.force_32bit_output);
63 TypeOracle::Scope type_oracle;
64 CurrentScope::Scope current_namespace(GlobalContext::GetDefaultNamespace());
65
66 // Two-step process of predeclaration + resolution allows to resolve type
67 // declarations independent of the order they are given.
68 PredeclarationVisitor::Predeclare(GlobalContext::ast());
69 PredeclarationVisitor::ResolvePredeclarations();
70
71 // Process other declarations.
72 DeclarationVisitor::Visit(GlobalContext::ast());
73
74 // A class types' fields are resolved here, which allows two class fields to
75 // mutually refer to each others.
76 TypeOracle::FinalizeAggregateTypes();
77
78 std::string output_directory = options.output_directory;
79
80 ImplementationVisitor implementation_visitor;
81 implementation_visitor.SetDryRun(output_directory.length() == 0);
82
83 implementation_visitor.GenerateInstanceTypes(output_directory);
84 implementation_visitor.BeginGeneratedFiles();
85 implementation_visitor.BeginDebugMacrosFile();
86
87 implementation_visitor.VisitAllDeclarables();
88
89 ReportAllUnusedMacros();
90
91 implementation_visitor.GenerateBuiltinDefinitionsAndInterfaceDescriptors(
92 output_directory);
93 implementation_visitor.GenerateVisitorLists(output_directory);
94 implementation_visitor.GenerateBitFields(output_directory);
95 implementation_visitor.GeneratePrintDefinitions(output_directory);
96 implementation_visitor.GenerateClassDefinitions(output_directory);
97 implementation_visitor.GenerateClassVerifiers(output_directory);
98 implementation_visitor.GenerateClassDebugReaders(output_directory);
99 implementation_visitor.GenerateEnumVerifiers(output_directory);
100 implementation_visitor.GenerateBodyDescriptors(output_directory);
101 implementation_visitor.GenerateExportedMacrosAssembler(output_directory);
102 implementation_visitor.GenerateCSATypes(output_directory);
103
104 implementation_visitor.EndGeneratedFiles();
105 implementation_visitor.EndDebugMacrosFile();
106 implementation_visitor.GenerateImplementation(output_directory);
107
108 if (GlobalContext::collect_language_server_data()) {
109 LanguageServerData::SetGlobalContext(std::move(GlobalContext::Get()));
110 LanguageServerData::SetTypeOracle(std::move(TypeOracle::Get()));
111 }
112 }
113
114 } // namespace
115
CompileTorque(const std::string & source,TorqueCompilerOptions options)116 TorqueCompilerResult CompileTorque(const std::string& source,
117 TorqueCompilerOptions options) {
118 SourceFileMap::Scope source_map_scope(options.v8_root);
119 CurrentSourceFile::Scope no_file_scope(
120 SourceFileMap::AddSource("dummy-filename.tq"));
121 CurrentAst::Scope ast_scope;
122 TorqueMessages::Scope messages_scope;
123 LanguageServerData::Scope server_data_scope;
124
125 TorqueCompilerResult result;
126 try {
127 ParseTorque(source);
128 CompileCurrentAst(options);
129 } catch (TorqueAbortCompilation&) {
130 // Do nothing. The relevant TorqueMessage is part of the
131 // TorqueMessages contextual.
132 }
133
134 result.source_file_map = SourceFileMap::Get();
135 result.language_server_data = std::move(LanguageServerData::Get());
136 result.messages = std::move(TorqueMessages::Get());
137
138 return result;
139 }
140
CompileTorque(std::vector<std::string> files,TorqueCompilerOptions options)141 TorqueCompilerResult CompileTorque(std::vector<std::string> files,
142 TorqueCompilerOptions options) {
143 SourceFileMap::Scope source_map_scope(options.v8_root);
144 CurrentSourceFile::Scope unknown_source_file_scope(SourceId::Invalid());
145 CurrentAst::Scope ast_scope;
146 TorqueMessages::Scope messages_scope;
147 LanguageServerData::Scope server_data_scope;
148
149 TorqueCompilerResult result;
150 try {
151 for (const auto& path : files) {
152 ReadAndParseTorqueFile(path);
153 }
154 CompileCurrentAst(options);
155 } catch (TorqueAbortCompilation&) {
156 // Do nothing. The relevant TorqueMessage is part of the
157 // TorqueMessages contextual.
158 }
159
160 result.source_file_map = SourceFileMap::Get();
161 result.language_server_data = std::move(LanguageServerData::Get());
162 result.messages = std::move(TorqueMessages::Get());
163
164 return result;
165 }
166
CompileTorqueForKythe(std::vector<TorqueCompilationUnit> units,TorqueCompilerOptions options,KytheConsumer * consumer)167 TorqueCompilerResult CompileTorqueForKythe(
168 std::vector<TorqueCompilationUnit> units, TorqueCompilerOptions options,
169 KytheConsumer* consumer) {
170 SourceFileMap::Scope source_map_scope(options.v8_root);
171 CurrentSourceFile::Scope unknown_source_file_scope(SourceId::Invalid());
172 CurrentAst::Scope ast_scope;
173 TorqueMessages::Scope messages_scope;
174 LanguageServerData::Scope server_data_scope;
175 KytheData::Scope kythe_scope;
176
177 KytheData::Get().SetConsumer(consumer);
178
179 TorqueCompilerResult result;
180 try {
181 for (const auto& unit : units) {
182 SourceId source_id = SourceFileMap::AddSource(unit.source_file_path);
183 CurrentSourceFile::Scope source_id_scope(source_id);
184 ParseTorque(unit.file_content);
185 }
186 CompileCurrentAst(options);
187 } catch (TorqueAbortCompilation&) {
188 // Do nothing. The relevant TorqueMessage is part of the
189 // TorqueMessages contextual.
190 }
191
192 result.source_file_map = SourceFileMap::Get();
193 result.language_server_data = std::move(LanguageServerData::Get());
194 result.messages = std::move(TorqueMessages::Get());
195
196 return result;
197 }
198
199 } // namespace torque
200 } // namespace internal
201 } // namespace v8
202