|  | // Copyright 2019 the V8 project authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "src/torque/torque-compiler.h" | 
|  |  | 
|  | #include <fstream> | 
|  | #include "src/torque/declarable.h" | 
|  | #include "src/torque/declaration-visitor.h" | 
|  | #include "src/torque/global-context.h" | 
|  | #include "src/torque/implementation-visitor.h" | 
|  | #include "src/torque/torque-parser.h" | 
|  | #include "src/torque/type-oracle.h" | 
|  |  | 
|  | namespace v8 { | 
|  | namespace internal { | 
|  | namespace torque { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | base::Optional<std::string> ReadFile(const std::string& path) { | 
|  | std::ifstream file_stream(path); | 
|  | if (!file_stream.good()) return base::nullopt; | 
|  |  | 
|  | return std::string{std::istreambuf_iterator<char>(file_stream), | 
|  | std::istreambuf_iterator<char>()}; | 
|  | } | 
|  |  | 
|  | void ReadAndParseTorqueFile(const std::string& path) { | 
|  | SourceId source_id = SourceFileMap::AddSource(path); | 
|  | CurrentSourceFile::Scope source_id_scope(source_id); | 
|  |  | 
|  | // path might be either a normal file path or an encoded URI. | 
|  | auto maybe_content = ReadFile(SourceFileMap::AbsolutePath(source_id)); | 
|  | if (!maybe_content) { | 
|  | if (auto maybe_path = FileUriDecode(path)) { | 
|  | maybe_content = ReadFile(*maybe_path); | 
|  | } | 
|  | } | 
|  |  | 
|  | if (!maybe_content) { | 
|  | Error("Cannot open file path/uri: ", path).Throw(); | 
|  | } | 
|  |  | 
|  | ParseTorque(*maybe_content); | 
|  | } | 
|  |  | 
|  | void CompileCurrentAst(TorqueCompilerOptions options) { | 
|  | GlobalContext::Scope global_context(std::move(CurrentAst::Get())); | 
|  | if (options.collect_language_server_data) { | 
|  | GlobalContext::SetCollectLanguageServerData(); | 
|  | } | 
|  | if (options.force_assert_statements) { | 
|  | GlobalContext::SetForceAssertStatements(); | 
|  | } | 
|  | TargetArchitecture::Scope target_architecture(options.force_32bit_output); | 
|  | TypeOracle::Scope type_oracle; | 
|  | CurrentScope::Scope current_namespace(GlobalContext::GetDefaultNamespace()); | 
|  |  | 
|  | // Two-step process of predeclaration + resolution allows to resolve type | 
|  | // declarations independent of the order they are given. | 
|  | PredeclarationVisitor::Predeclare(GlobalContext::ast()); | 
|  | PredeclarationVisitor::ResolvePredeclarations(); | 
|  |  | 
|  | // Process other declarations. | 
|  | DeclarationVisitor::Visit(GlobalContext::ast()); | 
|  |  | 
|  | // A class types' fields are resolved here, which allows two class fields to | 
|  | // mutually refer to each others. | 
|  | TypeOracle::FinalizeAggregateTypes(); | 
|  |  | 
|  | std::string output_directory = options.output_directory; | 
|  |  | 
|  | ImplementationVisitor implementation_visitor; | 
|  | implementation_visitor.SetDryRun(output_directory.length() == 0); | 
|  |  | 
|  | implementation_visitor.GenerateInstanceTypes(output_directory); | 
|  | implementation_visitor.BeginGeneratedFiles(); | 
|  | implementation_visitor.BeginRuntimeMacrosFile(); | 
|  |  | 
|  | implementation_visitor.VisitAllDeclarables(); | 
|  |  | 
|  | ReportAllUnusedMacros(); | 
|  |  | 
|  | implementation_visitor.GenerateBuiltinDefinitionsAndInterfaceDescriptors( | 
|  | output_directory); | 
|  | implementation_visitor.GenerateClassFieldOffsets(output_directory); | 
|  | implementation_visitor.GenerateBitFields(output_directory); | 
|  | implementation_visitor.GeneratePrintDefinitions(output_directory); | 
|  | implementation_visitor.GenerateClassDefinitions(output_directory); | 
|  | implementation_visitor.GenerateClassVerifiers(output_directory); | 
|  | implementation_visitor.GenerateClassDebugReaders(output_directory); | 
|  | implementation_visitor.GenerateEnumVerifiers(output_directory); | 
|  | implementation_visitor.GenerateBodyDescriptors(output_directory); | 
|  | implementation_visitor.GenerateExportedMacrosAssembler(output_directory); | 
|  | implementation_visitor.GenerateCSATypes(output_directory); | 
|  |  | 
|  | implementation_visitor.EndGeneratedFiles(); | 
|  | implementation_visitor.EndRuntimeMacrosFile(); | 
|  | implementation_visitor.GenerateImplementation(output_directory); | 
|  |  | 
|  | if (GlobalContext::collect_language_server_data()) { | 
|  | LanguageServerData::SetGlobalContext(std::move(GlobalContext::Get())); | 
|  | LanguageServerData::SetTypeOracle(std::move(TypeOracle::Get())); | 
|  | } | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | TorqueCompilerResult CompileTorque(const std::string& source, | 
|  | TorqueCompilerOptions options) { | 
|  | SourceFileMap::Scope source_map_scope(options.v8_root); | 
|  | CurrentSourceFile::Scope no_file_scope( | 
|  | SourceFileMap::AddSource("dummy-filename.tq")); | 
|  | CurrentAst::Scope ast_scope; | 
|  | TorqueMessages::Scope messages_scope; | 
|  | LanguageServerData::Scope server_data_scope; | 
|  |  | 
|  | TorqueCompilerResult result; | 
|  | try { | 
|  | ParseTorque(source); | 
|  | CompileCurrentAst(options); | 
|  | } catch (TorqueAbortCompilation&) { | 
|  | // Do nothing. The relevant TorqueMessage is part of the | 
|  | // TorqueMessages contextual. | 
|  | } | 
|  |  | 
|  | result.source_file_map = SourceFileMap::Get(); | 
|  | result.language_server_data = std::move(LanguageServerData::Get()); | 
|  | result.messages = std::move(TorqueMessages::Get()); | 
|  |  | 
|  | return result; | 
|  | } | 
|  |  | 
|  | TorqueCompilerResult CompileTorque(std::vector<std::string> files, | 
|  | TorqueCompilerOptions options) { | 
|  | SourceFileMap::Scope source_map_scope(options.v8_root); | 
|  | CurrentSourceFile::Scope unknown_source_file_scope(SourceId::Invalid()); | 
|  | CurrentAst::Scope ast_scope; | 
|  | TorqueMessages::Scope messages_scope; | 
|  | LanguageServerData::Scope server_data_scope; | 
|  |  | 
|  | TorqueCompilerResult result; | 
|  | try { | 
|  | for (const auto& path : files) { | 
|  | ReadAndParseTorqueFile(path); | 
|  | } | 
|  | CompileCurrentAst(options); | 
|  | } catch (TorqueAbortCompilation&) { | 
|  | // Do nothing. The relevant TorqueMessage is part of the | 
|  | // TorqueMessages contextual. | 
|  | } | 
|  |  | 
|  | result.source_file_map = SourceFileMap::Get(); | 
|  | result.language_server_data = std::move(LanguageServerData::Get()); | 
|  | result.messages = std::move(TorqueMessages::Get()); | 
|  |  | 
|  | return result; | 
|  | } | 
|  |  | 
|  | }  // namespace torque | 
|  | }  // namespace internal | 
|  | }  // namespace v8 |