11cb0ef41Sopenharmony_ci// Copyright 2019 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/torque/torque-compiler.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include <fstream>
81cb0ef41Sopenharmony_ci#include "src/torque/declarable.h"
91cb0ef41Sopenharmony_ci#include "src/torque/declaration-visitor.h"
101cb0ef41Sopenharmony_ci#include "src/torque/global-context.h"
111cb0ef41Sopenharmony_ci#include "src/torque/implementation-visitor.h"
121cb0ef41Sopenharmony_ci#include "src/torque/torque-parser.h"
131cb0ef41Sopenharmony_ci#include "src/torque/type-oracle.h"
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_cinamespace v8 {
161cb0ef41Sopenharmony_cinamespace internal {
171cb0ef41Sopenharmony_cinamespace torque {
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_cinamespace {
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_cibase::Optional<std::string> ReadFile(const std::string& path) {
221cb0ef41Sopenharmony_ci  std::ifstream file_stream(path);
231cb0ef41Sopenharmony_ci  if (!file_stream.good()) return base::nullopt;
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci  return std::string{std::istreambuf_iterator<char>(file_stream),
261cb0ef41Sopenharmony_ci                     std::istreambuf_iterator<char>()};
271cb0ef41Sopenharmony_ci}
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_civoid ReadAndParseTorqueFile(const std::string& path) {
301cb0ef41Sopenharmony_ci  SourceId source_id = SourceFileMap::AddSource(path);
311cb0ef41Sopenharmony_ci  CurrentSourceFile::Scope source_id_scope(source_id);
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci  // path might be either a normal file path or an encoded URI.
341cb0ef41Sopenharmony_ci  auto maybe_content = ReadFile(SourceFileMap::AbsolutePath(source_id));
351cb0ef41Sopenharmony_ci  if (!maybe_content) {
361cb0ef41Sopenharmony_ci    if (auto maybe_path = FileUriDecode(path)) {
371cb0ef41Sopenharmony_ci      maybe_content = ReadFile(*maybe_path);
381cb0ef41Sopenharmony_ci    }
391cb0ef41Sopenharmony_ci  }
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci  if (!maybe_content) {
421cb0ef41Sopenharmony_ci    Error("Cannot open file path/uri: ", path).Throw();
431cb0ef41Sopenharmony_ci  }
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci  ParseTorque(*maybe_content);
461cb0ef41Sopenharmony_ci}
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_civoid CompileCurrentAst(TorqueCompilerOptions options) {
491cb0ef41Sopenharmony_ci  GlobalContext::Scope global_context(std::move(CurrentAst::Get()));
501cb0ef41Sopenharmony_ci  if (options.collect_language_server_data) {
511cb0ef41Sopenharmony_ci    GlobalContext::SetCollectLanguageServerData();
521cb0ef41Sopenharmony_ci  }
531cb0ef41Sopenharmony_ci  if (options.collect_kythe_data) {
541cb0ef41Sopenharmony_ci    GlobalContext::SetCollectKytheData();
551cb0ef41Sopenharmony_ci  }
561cb0ef41Sopenharmony_ci  if (options.force_assert_statements) {
571cb0ef41Sopenharmony_ci    GlobalContext::SetForceAssertStatements();
581cb0ef41Sopenharmony_ci  }
591cb0ef41Sopenharmony_ci  if (options.annotate_ir) {
601cb0ef41Sopenharmony_ci    GlobalContext::SetAnnotateIR();
611cb0ef41Sopenharmony_ci  }
621cb0ef41Sopenharmony_ci  TargetArchitecture::Scope target_architecture(options.force_32bit_output);
631cb0ef41Sopenharmony_ci  TypeOracle::Scope type_oracle;
641cb0ef41Sopenharmony_ci  CurrentScope::Scope current_namespace(GlobalContext::GetDefaultNamespace());
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci  // Two-step process of predeclaration + resolution allows to resolve type
671cb0ef41Sopenharmony_ci  // declarations independent of the order they are given.
681cb0ef41Sopenharmony_ci  PredeclarationVisitor::Predeclare(GlobalContext::ast());
691cb0ef41Sopenharmony_ci  PredeclarationVisitor::ResolvePredeclarations();
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci  // Process other declarations.
721cb0ef41Sopenharmony_ci  DeclarationVisitor::Visit(GlobalContext::ast());
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci  // A class types' fields are resolved here, which allows two class fields to
751cb0ef41Sopenharmony_ci  // mutually refer to each others.
761cb0ef41Sopenharmony_ci  TypeOracle::FinalizeAggregateTypes();
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci  std::string output_directory = options.output_directory;
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci  ImplementationVisitor implementation_visitor;
811cb0ef41Sopenharmony_ci  implementation_visitor.SetDryRun(output_directory.length() == 0);
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci  implementation_visitor.GenerateInstanceTypes(output_directory);
841cb0ef41Sopenharmony_ci  implementation_visitor.BeginGeneratedFiles();
851cb0ef41Sopenharmony_ci  implementation_visitor.BeginDebugMacrosFile();
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci  implementation_visitor.VisitAllDeclarables();
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci  ReportAllUnusedMacros();
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci  implementation_visitor.GenerateBuiltinDefinitionsAndInterfaceDescriptors(
921cb0ef41Sopenharmony_ci      output_directory);
931cb0ef41Sopenharmony_ci  implementation_visitor.GenerateVisitorLists(output_directory);
941cb0ef41Sopenharmony_ci  implementation_visitor.GenerateBitFields(output_directory);
951cb0ef41Sopenharmony_ci  implementation_visitor.GeneratePrintDefinitions(output_directory);
961cb0ef41Sopenharmony_ci  implementation_visitor.GenerateClassDefinitions(output_directory);
971cb0ef41Sopenharmony_ci  implementation_visitor.GenerateClassVerifiers(output_directory);
981cb0ef41Sopenharmony_ci  implementation_visitor.GenerateClassDebugReaders(output_directory);
991cb0ef41Sopenharmony_ci  implementation_visitor.GenerateEnumVerifiers(output_directory);
1001cb0ef41Sopenharmony_ci  implementation_visitor.GenerateBodyDescriptors(output_directory);
1011cb0ef41Sopenharmony_ci  implementation_visitor.GenerateExportedMacrosAssembler(output_directory);
1021cb0ef41Sopenharmony_ci  implementation_visitor.GenerateCSATypes(output_directory);
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci  implementation_visitor.EndGeneratedFiles();
1051cb0ef41Sopenharmony_ci  implementation_visitor.EndDebugMacrosFile();
1061cb0ef41Sopenharmony_ci  implementation_visitor.GenerateImplementation(output_directory);
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci  if (GlobalContext::collect_language_server_data()) {
1091cb0ef41Sopenharmony_ci    LanguageServerData::SetGlobalContext(std::move(GlobalContext::Get()));
1101cb0ef41Sopenharmony_ci    LanguageServerData::SetTypeOracle(std::move(TypeOracle::Get()));
1111cb0ef41Sopenharmony_ci  }
1121cb0ef41Sopenharmony_ci}
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci}  // namespace
1151cb0ef41Sopenharmony_ci
1161cb0ef41Sopenharmony_ciTorqueCompilerResult CompileTorque(const std::string& source,
1171cb0ef41Sopenharmony_ci                                   TorqueCompilerOptions options) {
1181cb0ef41Sopenharmony_ci  SourceFileMap::Scope source_map_scope(options.v8_root);
1191cb0ef41Sopenharmony_ci  CurrentSourceFile::Scope no_file_scope(
1201cb0ef41Sopenharmony_ci      SourceFileMap::AddSource("dummy-filename.tq"));
1211cb0ef41Sopenharmony_ci  CurrentAst::Scope ast_scope;
1221cb0ef41Sopenharmony_ci  TorqueMessages::Scope messages_scope;
1231cb0ef41Sopenharmony_ci  LanguageServerData::Scope server_data_scope;
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci  TorqueCompilerResult result;
1261cb0ef41Sopenharmony_ci  try {
1271cb0ef41Sopenharmony_ci    ParseTorque(source);
1281cb0ef41Sopenharmony_ci    CompileCurrentAst(options);
1291cb0ef41Sopenharmony_ci  } catch (TorqueAbortCompilation&) {
1301cb0ef41Sopenharmony_ci    // Do nothing. The relevant TorqueMessage is part of the
1311cb0ef41Sopenharmony_ci    // TorqueMessages contextual.
1321cb0ef41Sopenharmony_ci  }
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci  result.source_file_map = SourceFileMap::Get();
1351cb0ef41Sopenharmony_ci  result.language_server_data = std::move(LanguageServerData::Get());
1361cb0ef41Sopenharmony_ci  result.messages = std::move(TorqueMessages::Get());
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci  return result;
1391cb0ef41Sopenharmony_ci}
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_ciTorqueCompilerResult CompileTorque(std::vector<std::string> files,
1421cb0ef41Sopenharmony_ci                                   TorqueCompilerOptions options) {
1431cb0ef41Sopenharmony_ci  SourceFileMap::Scope source_map_scope(options.v8_root);
1441cb0ef41Sopenharmony_ci  CurrentSourceFile::Scope unknown_source_file_scope(SourceId::Invalid());
1451cb0ef41Sopenharmony_ci  CurrentAst::Scope ast_scope;
1461cb0ef41Sopenharmony_ci  TorqueMessages::Scope messages_scope;
1471cb0ef41Sopenharmony_ci  LanguageServerData::Scope server_data_scope;
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_ci  TorqueCompilerResult result;
1501cb0ef41Sopenharmony_ci  try {
1511cb0ef41Sopenharmony_ci    for (const auto& path : files) {
1521cb0ef41Sopenharmony_ci      ReadAndParseTorqueFile(path);
1531cb0ef41Sopenharmony_ci    }
1541cb0ef41Sopenharmony_ci    CompileCurrentAst(options);
1551cb0ef41Sopenharmony_ci  } catch (TorqueAbortCompilation&) {
1561cb0ef41Sopenharmony_ci    // Do nothing. The relevant TorqueMessage is part of the
1571cb0ef41Sopenharmony_ci    // TorqueMessages contextual.
1581cb0ef41Sopenharmony_ci  }
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_ci  result.source_file_map = SourceFileMap::Get();
1611cb0ef41Sopenharmony_ci  result.language_server_data = std::move(LanguageServerData::Get());
1621cb0ef41Sopenharmony_ci  result.messages = std::move(TorqueMessages::Get());
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci  return result;
1651cb0ef41Sopenharmony_ci}
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ciTorqueCompilerResult CompileTorqueForKythe(
1681cb0ef41Sopenharmony_ci    std::vector<TorqueCompilationUnit> units, TorqueCompilerOptions options,
1691cb0ef41Sopenharmony_ci    KytheConsumer* consumer) {
1701cb0ef41Sopenharmony_ci  SourceFileMap::Scope source_map_scope(options.v8_root);
1711cb0ef41Sopenharmony_ci  CurrentSourceFile::Scope unknown_source_file_scope(SourceId::Invalid());
1721cb0ef41Sopenharmony_ci  CurrentAst::Scope ast_scope;
1731cb0ef41Sopenharmony_ci  TorqueMessages::Scope messages_scope;
1741cb0ef41Sopenharmony_ci  LanguageServerData::Scope server_data_scope;
1751cb0ef41Sopenharmony_ci  KytheData::Scope kythe_scope;
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci  KytheData::Get().SetConsumer(consumer);
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci  TorqueCompilerResult result;
1801cb0ef41Sopenharmony_ci  try {
1811cb0ef41Sopenharmony_ci    for (const auto& unit : units) {
1821cb0ef41Sopenharmony_ci      SourceId source_id = SourceFileMap::AddSource(unit.source_file_path);
1831cb0ef41Sopenharmony_ci      CurrentSourceFile::Scope source_id_scope(source_id);
1841cb0ef41Sopenharmony_ci      ParseTorque(unit.file_content);
1851cb0ef41Sopenharmony_ci    }
1861cb0ef41Sopenharmony_ci    CompileCurrentAst(options);
1871cb0ef41Sopenharmony_ci  } catch (TorqueAbortCompilation&) {
1881cb0ef41Sopenharmony_ci    // Do nothing. The relevant TorqueMessage is part of the
1891cb0ef41Sopenharmony_ci    // TorqueMessages contextual.
1901cb0ef41Sopenharmony_ci  }
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ci  result.source_file_map = SourceFileMap::Get();
1931cb0ef41Sopenharmony_ci  result.language_server_data = std::move(LanguageServerData::Get());
1941cb0ef41Sopenharmony_ci  result.messages = std::move(TorqueMessages::Get());
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ci  return result;
1971cb0ef41Sopenharmony_ci}
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ci}  // namespace torque
2001cb0ef41Sopenharmony_ci}  // namespace internal
2011cb0ef41Sopenharmony_ci}  // namespace v8
202