11cb0ef41Sopenharmony_ci// Copyright 2017 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/declaration-visitor.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include "src/torque/ast.h"
81cb0ef41Sopenharmony_ci#include "src/torque/kythe-data.h"
91cb0ef41Sopenharmony_ci#include "src/torque/server-data.h"
101cb0ef41Sopenharmony_ci#include "src/torque/type-inference.h"
111cb0ef41Sopenharmony_ci#include "src/torque/type-visitor.h"
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_cinamespace v8 {
141cb0ef41Sopenharmony_cinamespace internal {
151cb0ef41Sopenharmony_cinamespace torque {
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ciNamespace* GetOrCreateNamespace(const std::string& name) {
181cb0ef41Sopenharmony_ci  std::vector<Namespace*> existing_namespaces = FilterDeclarables<Namespace>(
191cb0ef41Sopenharmony_ci      Declarations::TryLookupShallow(QualifiedName(name)));
201cb0ef41Sopenharmony_ci  if (existing_namespaces.empty()) {
211cb0ef41Sopenharmony_ci    return Declarations::DeclareNamespace(name);
221cb0ef41Sopenharmony_ci  }
231cb0ef41Sopenharmony_ci  DCHECK_EQ(1, existing_namespaces.size());
241cb0ef41Sopenharmony_ci  return existing_namespaces.front();
251cb0ef41Sopenharmony_ci}
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_civoid PredeclarationVisitor::Predeclare(Declaration* decl) {
281cb0ef41Sopenharmony_ci  CurrentSourcePosition::Scope scope(decl->pos);
291cb0ef41Sopenharmony_ci  switch (decl->kind) {
301cb0ef41Sopenharmony_ci#define ENUM_ITEM(name)        \
311cb0ef41Sopenharmony_ci  case AstNode::Kind::k##name: \
321cb0ef41Sopenharmony_ci    return Predeclare(name::cast(decl));
331cb0ef41Sopenharmony_ci    AST_TYPE_DECLARATION_NODE_KIND_LIST(ENUM_ITEM)
341cb0ef41Sopenharmony_ci#undef ENUM_ITEM
351cb0ef41Sopenharmony_ci    case AstNode::Kind::kNamespaceDeclaration:
361cb0ef41Sopenharmony_ci      return Predeclare(NamespaceDeclaration::cast(decl));
371cb0ef41Sopenharmony_ci    case AstNode::Kind::kGenericCallableDeclaration:
381cb0ef41Sopenharmony_ci      return Predeclare(GenericCallableDeclaration::cast(decl));
391cb0ef41Sopenharmony_ci    case AstNode::Kind::kGenericTypeDeclaration:
401cb0ef41Sopenharmony_ci      return Predeclare(GenericTypeDeclaration::cast(decl));
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci    default:
431cb0ef41Sopenharmony_ci      // Only processes type declaration nodes, namespaces and generics.
441cb0ef41Sopenharmony_ci      break;
451cb0ef41Sopenharmony_ci  }
461cb0ef41Sopenharmony_ci}
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_civoid DeclarationVisitor::Visit(Declaration* decl) {
491cb0ef41Sopenharmony_ci  CurrentSourcePosition::Scope scope(decl->pos);
501cb0ef41Sopenharmony_ci  switch (decl->kind) {
511cb0ef41Sopenharmony_ci#define ENUM_ITEM(name)        \
521cb0ef41Sopenharmony_ci  case AstNode::Kind::k##name: \
531cb0ef41Sopenharmony_ci    return Visit(name::cast(decl));
541cb0ef41Sopenharmony_ci    AST_DECLARATION_NODE_KIND_LIST(ENUM_ITEM)
551cb0ef41Sopenharmony_ci#undef ENUM_ITEM
561cb0ef41Sopenharmony_ci    default:
571cb0ef41Sopenharmony_ci      UNIMPLEMENTED();
581cb0ef41Sopenharmony_ci  }
591cb0ef41Sopenharmony_ci}
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ciBuiltin* DeclarationVisitor::CreateBuiltin(BuiltinDeclaration* decl,
621cb0ef41Sopenharmony_ci                                           std::string external_name,
631cb0ef41Sopenharmony_ci                                           std::string readable_name,
641cb0ef41Sopenharmony_ci                                           Signature signature,
651cb0ef41Sopenharmony_ci                                           base::Optional<Statement*> body) {
661cb0ef41Sopenharmony_ci  const bool javascript = decl->javascript_linkage;
671cb0ef41Sopenharmony_ci  const bool varargs = decl->parameters.has_varargs;
681cb0ef41Sopenharmony_ci  Builtin::Kind kind = !javascript ? Builtin::kStub
691cb0ef41Sopenharmony_ci                                   : varargs ? Builtin::kVarArgsJavaScript
701cb0ef41Sopenharmony_ci                                             : Builtin::kFixedArgsJavaScript;
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci  if (varargs && !javascript) {
731cb0ef41Sopenharmony_ci    Error("Rest parameters require ", decl->name,
741cb0ef41Sopenharmony_ci          " to be a JavaScript builtin");
751cb0ef41Sopenharmony_ci  }
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci  if (javascript) {
781cb0ef41Sopenharmony_ci    if (!signature.return_type->IsSubtypeOf(TypeOracle::GetJSAnyType())) {
791cb0ef41Sopenharmony_ci      Error("Return type of JavaScript-linkage builtins has to be JSAny.")
801cb0ef41Sopenharmony_ci          .Position(decl->return_type->pos);
811cb0ef41Sopenharmony_ci    }
821cb0ef41Sopenharmony_ci    for (size_t i = signature.implicit_count;
831cb0ef41Sopenharmony_ci         i < signature.parameter_types.types.size(); ++i) {
841cb0ef41Sopenharmony_ci      const Type* parameter_type = signature.parameter_types.types[i];
851cb0ef41Sopenharmony_ci      if (!TypeOracle::GetJSAnyType()->IsSubtypeOf(parameter_type)) {
861cb0ef41Sopenharmony_ci        Error(
871cb0ef41Sopenharmony_ci            "Parameters of JavaScript-linkage builtins have to be a supertype "
881cb0ef41Sopenharmony_ci            "of JSAny.")
891cb0ef41Sopenharmony_ci            .Position(decl->parameters.types[i]->pos);
901cb0ef41Sopenharmony_ci      }
911cb0ef41Sopenharmony_ci    }
921cb0ef41Sopenharmony_ci  }
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ci  for (size_t i = 0; i < signature.types().size(); ++i) {
951cb0ef41Sopenharmony_ci    if (signature.types()[i]->StructSupertype()) {
961cb0ef41Sopenharmony_ci      Error("Builtin do not support structs as arguments, but argument ",
971cb0ef41Sopenharmony_ci            signature.parameter_names[i], " has type ", *signature.types()[i],
981cb0ef41Sopenharmony_ci            ".");
991cb0ef41Sopenharmony_ci    }
1001cb0ef41Sopenharmony_ci  }
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci  if (signature.return_type->StructSupertype() && javascript) {
1031cb0ef41Sopenharmony_ci    Error(
1041cb0ef41Sopenharmony_ci        "Builtins with JS linkage cannot return structs, but the return type "
1051cb0ef41Sopenharmony_ci        "is ",
1061cb0ef41Sopenharmony_ci        *signature.return_type, ".");
1071cb0ef41Sopenharmony_ci  }
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci  if (signature.return_type == TypeOracle::GetVoidType()) {
1101cb0ef41Sopenharmony_ci    Error("Builtins cannot have return type void.");
1111cb0ef41Sopenharmony_ci  }
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci  Builtin* builtin = Declarations::CreateBuiltin(std::move(external_name),
1141cb0ef41Sopenharmony_ci                                                 std::move(readable_name), kind,
1151cb0ef41Sopenharmony_ci                                                 std::move(signature), body);
1161cb0ef41Sopenharmony_ci  // TODO(v8:12261): Recheck this.
1171cb0ef41Sopenharmony_ci  // builtin->SetIdentifierPosition(decl->name->pos);
1181cb0ef41Sopenharmony_ci  return builtin;
1191cb0ef41Sopenharmony_ci}
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_civoid DeclarationVisitor::Visit(ExternalBuiltinDeclaration* decl) {
1221cb0ef41Sopenharmony_ci  Builtin* builtin =
1231cb0ef41Sopenharmony_ci      CreateBuiltin(decl, decl->name->value, decl->name->value,
1241cb0ef41Sopenharmony_ci                    TypeVisitor::MakeSignature(decl), base::nullopt);
1251cb0ef41Sopenharmony_ci  builtin->SetIdentifierPosition(decl->name->pos);
1261cb0ef41Sopenharmony_ci  Declarations::Declare(decl->name->value, builtin);
1271cb0ef41Sopenharmony_ci}
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_civoid DeclarationVisitor::Visit(ExternalRuntimeDeclaration* decl) {
1301cb0ef41Sopenharmony_ci  Signature signature = TypeVisitor::MakeSignature(decl);
1311cb0ef41Sopenharmony_ci  if (signature.parameter_types.types.size() == 0) {
1321cb0ef41Sopenharmony_ci    ReportError(
1331cb0ef41Sopenharmony_ci        "Missing parameters for runtime function, at least the context "
1341cb0ef41Sopenharmony_ci        "parameter is required.");
1351cb0ef41Sopenharmony_ci  }
1361cb0ef41Sopenharmony_ci  if (!(signature.parameter_types.types[0] == TypeOracle::GetContextType() ||
1371cb0ef41Sopenharmony_ci        signature.parameter_types.types[0] == TypeOracle::GetNoContextType())) {
1381cb0ef41Sopenharmony_ci    ReportError(
1391cb0ef41Sopenharmony_ci        "first parameter to runtime functions has to be the context and have "
1401cb0ef41Sopenharmony_ci        "type Context or NoContext, but found type ",
1411cb0ef41Sopenharmony_ci        *signature.parameter_types.types[0]);
1421cb0ef41Sopenharmony_ci  }
1431cb0ef41Sopenharmony_ci  if (!(signature.return_type->IsSubtypeOf(TypeOracle::GetStrongTaggedType()) ||
1441cb0ef41Sopenharmony_ci        signature.return_type == TypeOracle::GetVoidType() ||
1451cb0ef41Sopenharmony_ci        signature.return_type == TypeOracle::GetNeverType())) {
1461cb0ef41Sopenharmony_ci    ReportError(
1471cb0ef41Sopenharmony_ci        "runtime functions can only return strong tagged values, but "
1481cb0ef41Sopenharmony_ci        "found type ",
1491cb0ef41Sopenharmony_ci        *signature.return_type);
1501cb0ef41Sopenharmony_ci  }
1511cb0ef41Sopenharmony_ci  for (const Type* parameter_type : signature.parameter_types.types) {
1521cb0ef41Sopenharmony_ci    if (!parameter_type->IsSubtypeOf(TypeOracle::GetStrongTaggedType())) {
1531cb0ef41Sopenharmony_ci      ReportError(
1541cb0ef41Sopenharmony_ci          "runtime functions can only take strong tagged parameters, but "
1551cb0ef41Sopenharmony_ci          "found type ",
1561cb0ef41Sopenharmony_ci          *parameter_type);
1571cb0ef41Sopenharmony_ci    }
1581cb0ef41Sopenharmony_ci  }
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_ci  RuntimeFunction* function =
1611cb0ef41Sopenharmony_ci      Declarations::DeclareRuntimeFunction(decl->name->value, signature);
1621cb0ef41Sopenharmony_ci  function->SetIdentifierPosition(decl->name->pos);
1631cb0ef41Sopenharmony_ci  function->SetPosition(decl->pos);
1641cb0ef41Sopenharmony_ci  if (GlobalContext::collect_kythe_data()) {
1651cb0ef41Sopenharmony_ci    KytheData::AddFunctionDefinition(function);
1661cb0ef41Sopenharmony_ci  }
1671cb0ef41Sopenharmony_ci}
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_civoid DeclarationVisitor::Visit(ExternalMacroDeclaration* decl) {
1701cb0ef41Sopenharmony_ci  Macro* macro = Declarations::DeclareMacro(
1711cb0ef41Sopenharmony_ci      decl->name->value, true, decl->external_assembler_name,
1721cb0ef41Sopenharmony_ci      TypeVisitor::MakeSignature(decl), base::nullopt, decl->op);
1731cb0ef41Sopenharmony_ci  macro->SetIdentifierPosition(decl->name->pos);
1741cb0ef41Sopenharmony_ci  macro->SetPosition(decl->pos);
1751cb0ef41Sopenharmony_ci  if (GlobalContext::collect_kythe_data()) {
1761cb0ef41Sopenharmony_ci    KytheData::AddFunctionDefinition(macro);
1771cb0ef41Sopenharmony_ci  }
1781cb0ef41Sopenharmony_ci}
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_civoid DeclarationVisitor::Visit(TorqueBuiltinDeclaration* decl) {
1811cb0ef41Sopenharmony_ci  auto builtin = CreateBuiltin(decl, decl->name->value, decl->name->value,
1821cb0ef41Sopenharmony_ci                               TypeVisitor::MakeSignature(decl), decl->body);
1831cb0ef41Sopenharmony_ci  builtin->SetIdentifierPosition(decl->name->pos);
1841cb0ef41Sopenharmony_ci  builtin->SetPosition(decl->pos);
1851cb0ef41Sopenharmony_ci  Declarations::Declare(decl->name->value, builtin);
1861cb0ef41Sopenharmony_ci}
1871cb0ef41Sopenharmony_ci
1881cb0ef41Sopenharmony_civoid DeclarationVisitor::Visit(TorqueMacroDeclaration* decl) {
1891cb0ef41Sopenharmony_ci  Macro* macro = Declarations::DeclareMacro(
1901cb0ef41Sopenharmony_ci      decl->name->value, decl->export_to_csa, base::nullopt,
1911cb0ef41Sopenharmony_ci      TypeVisitor::MakeSignature(decl), decl->body, decl->op);
1921cb0ef41Sopenharmony_ci  macro->SetIdentifierPosition(decl->name->pos);
1931cb0ef41Sopenharmony_ci  macro->SetPosition(decl->pos);
1941cb0ef41Sopenharmony_ci  if (GlobalContext::collect_kythe_data()) {
1951cb0ef41Sopenharmony_ci    KytheData::AddFunctionDefinition(macro);
1961cb0ef41Sopenharmony_ci  }
1971cb0ef41Sopenharmony_ci}
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_civoid DeclarationVisitor::Visit(IntrinsicDeclaration* decl) {
2001cb0ef41Sopenharmony_ci  Declarations::DeclareIntrinsic(decl->name->value,
2011cb0ef41Sopenharmony_ci                                 TypeVisitor::MakeSignature(decl));
2021cb0ef41Sopenharmony_ci}
2031cb0ef41Sopenharmony_ci
2041cb0ef41Sopenharmony_civoid DeclarationVisitor::Visit(ConstDeclaration* decl) {
2051cb0ef41Sopenharmony_ci  auto constant = Declarations::DeclareNamespaceConstant(
2061cb0ef41Sopenharmony_ci      decl->name, TypeVisitor::ComputeType(decl->type), decl->expression);
2071cb0ef41Sopenharmony_ci  if (GlobalContext::collect_kythe_data()) {
2081cb0ef41Sopenharmony_ci    KytheData::AddConstantDefinition(constant);
2091cb0ef41Sopenharmony_ci  }
2101cb0ef41Sopenharmony_ci}
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_civoid DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
2131cb0ef41Sopenharmony_ci  std::vector<GenericCallable*> generic_list =
2141cb0ef41Sopenharmony_ci      Declarations::LookupGeneric(decl->name->value);
2151cb0ef41Sopenharmony_ci  // Find the matching generic specialization based on the concrete parameter
2161cb0ef41Sopenharmony_ci  // list.
2171cb0ef41Sopenharmony_ci  GenericCallable* matching_generic = nullptr;
2181cb0ef41Sopenharmony_ci  Signature signature_with_types = TypeVisitor::MakeSignature(decl);
2191cb0ef41Sopenharmony_ci  for (GenericCallable* generic : generic_list) {
2201cb0ef41Sopenharmony_ci    // This argument inference is just to trigger constraint checking on the
2211cb0ef41Sopenharmony_ci    // generic arguments.
2221cb0ef41Sopenharmony_ci    TypeArgumentInference inference = generic->InferSpecializationTypes(
2231cb0ef41Sopenharmony_ci        TypeVisitor::ComputeTypeVector(decl->generic_parameters), {});
2241cb0ef41Sopenharmony_ci    if (inference.HasFailed()) {
2251cb0ef41Sopenharmony_ci      continue;
2261cb0ef41Sopenharmony_ci    }
2271cb0ef41Sopenharmony_ci    Signature generic_signature_with_types =
2281cb0ef41Sopenharmony_ci        MakeSpecializedSignature(SpecializationKey<GenericCallable>{
2291cb0ef41Sopenharmony_ci            generic, TypeVisitor::ComputeTypeVector(decl->generic_parameters)});
2301cb0ef41Sopenharmony_ci    if (signature_with_types.HasSameTypesAs(generic_signature_with_types,
2311cb0ef41Sopenharmony_ci                                            ParameterMode::kIgnoreImplicit)) {
2321cb0ef41Sopenharmony_ci      if (matching_generic != nullptr) {
2331cb0ef41Sopenharmony_ci        std::stringstream stream;
2341cb0ef41Sopenharmony_ci        stream << "specialization of " << decl->name
2351cb0ef41Sopenharmony_ci               << " is ambigous, it matches more than one generic declaration ("
2361cb0ef41Sopenharmony_ci               << *matching_generic << " and " << *generic << ")";
2371cb0ef41Sopenharmony_ci        ReportError(stream.str());
2381cb0ef41Sopenharmony_ci      }
2391cb0ef41Sopenharmony_ci      matching_generic = generic;
2401cb0ef41Sopenharmony_ci    }
2411cb0ef41Sopenharmony_ci  }
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ci  if (matching_generic == nullptr) {
2441cb0ef41Sopenharmony_ci    std::stringstream stream;
2451cb0ef41Sopenharmony_ci    if (generic_list.size() == 0) {
2461cb0ef41Sopenharmony_ci      stream << "no generic defined with the name " << decl->name;
2471cb0ef41Sopenharmony_ci      ReportError(stream.str());
2481cb0ef41Sopenharmony_ci    }
2491cb0ef41Sopenharmony_ci    stream << "specialization of " << decl->name
2501cb0ef41Sopenharmony_ci           << " doesn't match any generic declaration\n";
2511cb0ef41Sopenharmony_ci    stream << "specialization signature:";
2521cb0ef41Sopenharmony_ci    stream << "\n  " << signature_with_types;
2531cb0ef41Sopenharmony_ci    stream << "\ncandidates are:";
2541cb0ef41Sopenharmony_ci    for (GenericCallable* generic : generic_list) {
2551cb0ef41Sopenharmony_ci      stream << "\n  "
2561cb0ef41Sopenharmony_ci             << MakeSpecializedSignature(SpecializationKey<GenericCallable>{
2571cb0ef41Sopenharmony_ci                    generic,
2581cb0ef41Sopenharmony_ci                    TypeVisitor::ComputeTypeVector(decl->generic_parameters)});
2591cb0ef41Sopenharmony_ci    }
2601cb0ef41Sopenharmony_ci    ReportError(stream.str());
2611cb0ef41Sopenharmony_ci  }
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_ci  if (GlobalContext::collect_language_server_data()) {
2641cb0ef41Sopenharmony_ci    LanguageServerData::AddDefinition(decl->name->pos,
2651cb0ef41Sopenharmony_ci                                      matching_generic->IdentifierPosition());
2661cb0ef41Sopenharmony_ci  }
2671cb0ef41Sopenharmony_ci
2681cb0ef41Sopenharmony_ci  CallableDeclaration* generic_declaration = matching_generic->declaration();
2691cb0ef41Sopenharmony_ci
2701cb0ef41Sopenharmony_ci  Specialize(SpecializationKey<GenericCallable>{matching_generic,
2711cb0ef41Sopenharmony_ci                                                TypeVisitor::ComputeTypeVector(
2721cb0ef41Sopenharmony_ci                                                    decl->generic_parameters)},
2731cb0ef41Sopenharmony_ci             generic_declaration, decl, decl->body, decl->pos);
2741cb0ef41Sopenharmony_ci}
2751cb0ef41Sopenharmony_ci
2761cb0ef41Sopenharmony_civoid DeclarationVisitor::Visit(ExternConstDeclaration* decl) {
2771cb0ef41Sopenharmony_ci  const Type* type = TypeVisitor::ComputeType(decl->type);
2781cb0ef41Sopenharmony_ci  if (!type->IsConstexpr()) {
2791cb0ef41Sopenharmony_ci    std::stringstream stream;
2801cb0ef41Sopenharmony_ci    stream << "extern constants must have constexpr type, but found: \""
2811cb0ef41Sopenharmony_ci           << *type << "\"\n";
2821cb0ef41Sopenharmony_ci    ReportError(stream.str());
2831cb0ef41Sopenharmony_ci  }
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_ci  ExternConstant* constant =
2861cb0ef41Sopenharmony_ci      Declarations::DeclareExternConstant(decl->name, type, decl->literal);
2871cb0ef41Sopenharmony_ci  if (GlobalContext::collect_kythe_data()) {
2881cb0ef41Sopenharmony_ci    KytheData::AddConstantDefinition(constant);
2891cb0ef41Sopenharmony_ci  }
2901cb0ef41Sopenharmony_ci}
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_civoid DeclarationVisitor::Visit(CppIncludeDeclaration* decl) {
2931cb0ef41Sopenharmony_ci  GlobalContext::AddCppInclude(decl->include_path);
2941cb0ef41Sopenharmony_ci}
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_civoid DeclarationVisitor::DeclareSpecializedTypes(
2971cb0ef41Sopenharmony_ci    const SpecializationKey<GenericCallable>& key) {
2981cb0ef41Sopenharmony_ci  size_t i = 0;
2991cb0ef41Sopenharmony_ci  const std::size_t generic_parameter_count =
3001cb0ef41Sopenharmony_ci      key.generic->generic_parameters().size();
3011cb0ef41Sopenharmony_ci  if (generic_parameter_count != key.specialized_types.size()) {
3021cb0ef41Sopenharmony_ci    std::stringstream stream;
3031cb0ef41Sopenharmony_ci    stream << "Wrong generic argument count for specialization of \""
3041cb0ef41Sopenharmony_ci           << key.generic->name() << "\", expected: " << generic_parameter_count
3051cb0ef41Sopenharmony_ci           << ", actual: " << key.specialized_types.size();
3061cb0ef41Sopenharmony_ci    ReportError(stream.str());
3071cb0ef41Sopenharmony_ci  }
3081cb0ef41Sopenharmony_ci
3091cb0ef41Sopenharmony_ci  for (auto type : key.specialized_types) {
3101cb0ef41Sopenharmony_ci    Identifier* generic_type_name = key.generic->generic_parameters()[i++].name;
3111cb0ef41Sopenharmony_ci    TypeAlias* alias = Declarations::DeclareType(generic_type_name, type);
3121cb0ef41Sopenharmony_ci    alias->SetIsUserDefined(false);
3131cb0ef41Sopenharmony_ci  }
3141cb0ef41Sopenharmony_ci}
3151cb0ef41Sopenharmony_ci
3161cb0ef41Sopenharmony_ciSignature DeclarationVisitor::MakeSpecializedSignature(
3171cb0ef41Sopenharmony_ci    const SpecializationKey<GenericCallable>& key) {
3181cb0ef41Sopenharmony_ci  CurrentScope::Scope generic_scope(key.generic->ParentScope());
3191cb0ef41Sopenharmony_ci  // Create a temporary fake-namespace just to temporarily declare the
3201cb0ef41Sopenharmony_ci  // specialization aliases for the generic types to create a signature.
3211cb0ef41Sopenharmony_ci  Namespace tmp_namespace("_tmp");
3221cb0ef41Sopenharmony_ci  CurrentScope::Scope tmp_namespace_scope(&tmp_namespace);
3231cb0ef41Sopenharmony_ci  DeclareSpecializedTypes(key);
3241cb0ef41Sopenharmony_ci  return TypeVisitor::MakeSignature(key.generic->declaration());
3251cb0ef41Sopenharmony_ci}
3261cb0ef41Sopenharmony_ci
3271cb0ef41Sopenharmony_ciCallable* DeclarationVisitor::SpecializeImplicit(
3281cb0ef41Sopenharmony_ci    const SpecializationKey<GenericCallable>& key) {
3291cb0ef41Sopenharmony_ci  base::Optional<Statement*> body = key.generic->CallableBody();
3301cb0ef41Sopenharmony_ci  if (!body && IntrinsicDeclaration::DynamicCast(key.generic->declaration()) ==
3311cb0ef41Sopenharmony_ci                   nullptr) {
3321cb0ef41Sopenharmony_ci    ReportError("missing specialization of ", key.generic->name(),
3331cb0ef41Sopenharmony_ci                " with types <", key.specialized_types, "> declared at ",
3341cb0ef41Sopenharmony_ci                key.generic->Position());
3351cb0ef41Sopenharmony_ci  }
3361cb0ef41Sopenharmony_ci  SpecializationRequester requester{CurrentSourcePosition::Get(),
3371cb0ef41Sopenharmony_ci                                    CurrentScope::Get(), ""};
3381cb0ef41Sopenharmony_ci  CurrentScope::Scope generic_scope(key.generic->ParentScope());
3391cb0ef41Sopenharmony_ci  Callable* result = Specialize(key, key.generic->declaration(), base::nullopt,
3401cb0ef41Sopenharmony_ci                                body, CurrentSourcePosition::Get());
3411cb0ef41Sopenharmony_ci  result->SetIsUserDefined(false);
3421cb0ef41Sopenharmony_ci  requester.name = result->ReadableName();
3431cb0ef41Sopenharmony_ci  result->SetSpecializationRequester(requester);
3441cb0ef41Sopenharmony_ci  CurrentScope::Scope callable_scope(result);
3451cb0ef41Sopenharmony_ci  DeclareSpecializedTypes(key);
3461cb0ef41Sopenharmony_ci  return result;
3471cb0ef41Sopenharmony_ci}
3481cb0ef41Sopenharmony_ci
3491cb0ef41Sopenharmony_ciCallable* DeclarationVisitor::Specialize(
3501cb0ef41Sopenharmony_ci    const SpecializationKey<GenericCallable>& key,
3511cb0ef41Sopenharmony_ci    CallableDeclaration* declaration,
3521cb0ef41Sopenharmony_ci    base::Optional<const SpecializationDeclaration*> explicit_specialization,
3531cb0ef41Sopenharmony_ci    base::Optional<Statement*> body, SourcePosition position) {
3541cb0ef41Sopenharmony_ci  CurrentSourcePosition::Scope pos_scope(position);
3551cb0ef41Sopenharmony_ci  size_t generic_parameter_count = key.generic->generic_parameters().size();
3561cb0ef41Sopenharmony_ci  if (generic_parameter_count != key.specialized_types.size()) {
3571cb0ef41Sopenharmony_ci    std::stringstream stream;
3581cb0ef41Sopenharmony_ci    stream << "number of template parameters ("
3591cb0ef41Sopenharmony_ci           << std::to_string(key.specialized_types.size())
3601cb0ef41Sopenharmony_ci           << ") to intantiation of generic " << declaration->name
3611cb0ef41Sopenharmony_ci           << " doesnt match the generic's declaration ("
3621cb0ef41Sopenharmony_ci           << std::to_string(generic_parameter_count) << ")";
3631cb0ef41Sopenharmony_ci    ReportError(stream.str());
3641cb0ef41Sopenharmony_ci  }
3651cb0ef41Sopenharmony_ci  if (key.generic->GetSpecialization(key.specialized_types)) {
3661cb0ef41Sopenharmony_ci    ReportError("cannot redeclare specialization of ", key.generic->name(),
3671cb0ef41Sopenharmony_ci                " with types <", key.specialized_types, ">");
3681cb0ef41Sopenharmony_ci  }
3691cb0ef41Sopenharmony_ci
3701cb0ef41Sopenharmony_ci  Signature type_signature =
3711cb0ef41Sopenharmony_ci      explicit_specialization
3721cb0ef41Sopenharmony_ci          ? TypeVisitor::MakeSignature(*explicit_specialization)
3731cb0ef41Sopenharmony_ci          : MakeSpecializedSignature(key);
3741cb0ef41Sopenharmony_ci
3751cb0ef41Sopenharmony_ci  std::string generated_name = Declarations::GetGeneratedCallableName(
3761cb0ef41Sopenharmony_ci      declaration->name->value, key.specialized_types);
3771cb0ef41Sopenharmony_ci  std::stringstream readable_name;
3781cb0ef41Sopenharmony_ci  readable_name << declaration->name->value << "<";
3791cb0ef41Sopenharmony_ci  bool first = true;
3801cb0ef41Sopenharmony_ci  for (const Type* t : key.specialized_types) {
3811cb0ef41Sopenharmony_ci    if (!first) readable_name << ", ";
3821cb0ef41Sopenharmony_ci    readable_name << *t;
3831cb0ef41Sopenharmony_ci    first = false;
3841cb0ef41Sopenharmony_ci  }
3851cb0ef41Sopenharmony_ci  readable_name << ">";
3861cb0ef41Sopenharmony_ci  Callable* callable;
3871cb0ef41Sopenharmony_ci  if (MacroDeclaration::DynamicCast(declaration) != nullptr) {
3881cb0ef41Sopenharmony_ci    callable =
3891cb0ef41Sopenharmony_ci        Declarations::CreateTorqueMacro(generated_name, readable_name.str(),
3901cb0ef41Sopenharmony_ci                                        false, type_signature, *body, true);
3911cb0ef41Sopenharmony_ci  } else if (IntrinsicDeclaration::DynamicCast(declaration) != nullptr) {
3921cb0ef41Sopenharmony_ci    callable =
3931cb0ef41Sopenharmony_ci        Declarations::CreateIntrinsic(declaration->name->value, type_signature);
3941cb0ef41Sopenharmony_ci  } else {
3951cb0ef41Sopenharmony_ci    BuiltinDeclaration* builtin = BuiltinDeclaration::cast(declaration);
3961cb0ef41Sopenharmony_ci    callable =
3971cb0ef41Sopenharmony_ci        CreateBuiltin(builtin, GlobalContext::MakeUniqueName(generated_name),
3981cb0ef41Sopenharmony_ci                      readable_name.str(), type_signature, *body);
3991cb0ef41Sopenharmony_ci  }
4001cb0ef41Sopenharmony_ci  key.generic->AddSpecialization(key.specialized_types, callable);
4011cb0ef41Sopenharmony_ci  return callable;
4021cb0ef41Sopenharmony_ci}
4031cb0ef41Sopenharmony_ci
4041cb0ef41Sopenharmony_civoid PredeclarationVisitor::ResolvePredeclarations() {
4051cb0ef41Sopenharmony_ci  const auto& all_declarables = GlobalContext::AllDeclarables();
4061cb0ef41Sopenharmony_ci  for (size_t i = 0; i < all_declarables.size(); ++i) {
4071cb0ef41Sopenharmony_ci    Declarable* declarable = all_declarables[i].get();
4081cb0ef41Sopenharmony_ci    if (const TypeAlias* alias = TypeAlias::DynamicCast(declarable)) {
4091cb0ef41Sopenharmony_ci      CurrentScope::Scope scope_activator(alias->ParentScope());
4101cb0ef41Sopenharmony_ci      CurrentSourcePosition::Scope position_activator(alias->Position());
4111cb0ef41Sopenharmony_ci      alias->Resolve();
4121cb0ef41Sopenharmony_ci    }
4131cb0ef41Sopenharmony_ci  }
4141cb0ef41Sopenharmony_ci}
4151cb0ef41Sopenharmony_ci
4161cb0ef41Sopenharmony_ci}  // namespace torque
4171cb0ef41Sopenharmony_ci}  // namespace internal
4181cb0ef41Sopenharmony_ci}  // namespace v8
419