LCOV - code coverage report
Current view: top level - src/torque - declaration-visitor.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 230 323 71.2 %
Date: 2019-01-20 Functions: 23 25 92.0 %

          Line data    Source code
       1             : // Copyright 2017 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/declaration-visitor.h"
       6             : #include "src/torque/ast.h"
       7             : 
       8             : namespace v8 {
       9             : namespace internal {
      10             : namespace torque {
      11             : 
      12        1090 : void DeclarationVisitor::Visit(Declaration* decl) {
      13        1090 :   CurrentSourcePosition::Scope scope(decl->pos);
      14        1090 :   switch (decl->kind) {
      15             : #define ENUM_ITEM(name)        \
      16             :   case AstNode::Kind::k##name: \
      17             :     return Visit(name::cast(decl));
      18        1042 :     AST_DECLARATION_NODE_KIND_LIST(ENUM_ITEM)
      19             : #undef ENUM_ITEM
      20             :     default:
      21           0 :       UNIMPLEMENTED();
      22             :   }
      23             : }
      24             : 
      25         649 : void DeclarationVisitor::Visit(CallableNode* decl, const Signature& signature,
      26             :                                base::Optional<Statement*> body) {
      27         649 :   switch (decl->kind) {
      28             : #define ENUM_ITEM(name)        \
      29             :   case AstNode::Kind::k##name: \
      30             :     return Visit(name::cast(decl), signature, body);
      31         649 :     AST_CALLABLE_NODE_KIND_LIST(ENUM_ITEM)
      32             : #undef ENUM_ITEM
      33             :     default:
      34           0 :       UNIMPLEMENTED();
      35             :   }
      36             : }
      37             : 
      38         134 : Builtin* DeclarationVisitor::CreateBuiltin(BuiltinDeclaration* decl,
      39             :                                            std::string external_name,
      40             :                                            std::string readable_name,
      41             :                                            Signature signature,
      42             :                                            base::Optional<Statement*> body) {
      43         134 :   const bool javascript = decl->javascript_linkage;
      44         134 :   const bool varargs = decl->signature->parameters.has_varargs;
      45             :   Builtin::Kind kind = !javascript ? Builtin::kStub
      46             :                                    : varargs ? Builtin::kVarArgsJavaScript
      47         134 :                                              : Builtin::kFixedArgsJavaScript;
      48             : 
      49         536 :   if (signature.types().size() == 0 ||
      50             :       !(signature.types()[0] ==
      51         536 :         Declarations::LookupGlobalType(CONTEXT_TYPE_STRING))) {
      52           0 :     std::stringstream stream;
      53           0 :     stream << "first parameter to builtin " << decl->name
      54           0 :            << " is not a context but should be";
      55           0 :     ReportError(stream.str());
      56             :   }
      57             : 
      58         134 :   if (varargs && !javascript) {
      59           0 :     std::stringstream stream;
      60           0 :     stream << "builtin " << decl->name
      61           0 :            << " with rest parameters must be a JavaScript builtin";
      62           0 :     ReportError(stream.str());
      63             :   }
      64             : 
      65         134 :   if (javascript) {
      66         188 :     if (signature.types().size() < 2 ||
      67             :         !(signature.types()[1] ==
      68         188 :           Declarations::LookupGlobalType(OBJECT_TYPE_STRING))) {
      69           0 :       std::stringstream stream;
      70           0 :       stream << "second parameter to javascript builtin " << decl->name
      71           0 :              << " is " << *signature.types()[1] << " but should be Object";
      72           0 :       ReportError(stream.str());
      73             :     }
      74             :   }
      75             : 
      76         134 :   if (const StructType* struct_type =
      77         134 :           StructType::DynamicCast(signature.return_type)) {
      78           0 :     std::stringstream stream;
      79           0 :     stream << "builtins (in this case" << decl->name
      80           0 :            << ") cannot return structs (in this case " << struct_type->name()
      81           0 :            << ")";
      82           0 :     ReportError(stream.str());
      83             :   }
      84             : 
      85             :   return Declarations::CreateBuiltin(
      86             :       std::move(external_name), std::move(readable_name), kind,
      87         536 :       std::move(signature), decl->transitioning, body);
      88             : }
      89             : 
      90          11 : void DeclarationVisitor::Visit(ExternalRuntimeDeclaration* decl,
      91             :                                const Signature& signature,
      92             :                                base::Optional<Statement*> body) {
      93          11 :   if (GlobalContext::verbose()) {
      94           0 :     std::cout << "found declaration of external runtime " << decl->name
      95           0 :               << " with signature ";
      96             :   }
      97             : 
      98          44 :   if (signature.parameter_types.types.size() == 0 ||
      99             :       !(signature.parameter_types.types[0] ==
     100          44 :         Declarations::LookupGlobalType(CONTEXT_TYPE_STRING))) {
     101           0 :     std::stringstream stream;
     102           0 :     stream << "first parameter to runtime " << decl->name
     103           0 :            << " is not a context but should be";
     104           0 :     ReportError(stream.str());
     105             :   }
     106             : 
     107          22 :   if (signature.return_type->IsStructType()) {
     108           0 :     std::stringstream stream;
     109           0 :     stream << "runtime functions (in this case" << decl->name
     110           0 :            << ") cannot return structs (in this case "
     111           0 :            << static_cast<const StructType*>(signature.return_type)->name()
     112           0 :            << ")";
     113           0 :     ReportError(stream.str());
     114             :   }
     115             : 
     116             :   Declarations::DeclareRuntimeFunction(decl->name, signature,
     117          11 :                                        decl->transitioning);
     118          11 : }
     119             : 
     120         356 : void DeclarationVisitor::Visit(ExternalMacroDeclaration* decl,
     121             :                                const Signature& signature,
     122             :                                base::Optional<Statement*> body) {
     123         356 :   if (GlobalContext::verbose()) {
     124           0 :     std::cout << "found declaration of external macro " << decl->name
     125           0 :               << " with signature ";
     126             :   }
     127             : 
     128             :   Declarations::DeclareMacro(decl->name, decl->external_assembler_name,
     129        1424 :                              signature, decl->transitioning, body, decl->op);
     130         356 : }
     131             : 
     132          64 : void DeclarationVisitor::Visit(TorqueBuiltinDeclaration* decl,
     133             :                                const Signature& signature,
     134             :                                base::Optional<Statement*> body) {
     135             :   Declarations::Declare(
     136         192 :       decl->name, CreateBuiltin(decl, decl->name, decl->name, signature, body));
     137          64 : }
     138             : 
     139         204 : void DeclarationVisitor::Visit(TorqueMacroDeclaration* decl,
     140             :                                const Signature& signature,
     141             :                                base::Optional<Statement*> body) {
     142             :   Declarations::DeclareMacro(decl->name, base::nullopt, signature,
     143         816 :                              decl->transitioning, body, decl->op);
     144         204 : }
     145             : 
     146           0 : void DeclarationVisitor::Visit(IntrinsicDeclaration* decl,
     147             :                                const Signature& signature,
     148             :                                base::Optional<Statement*> body) {
     149           0 :   Declarations::DeclareIntrinsic(decl->name, signature);
     150           0 : }
     151             : 
     152          40 : void DeclarationVisitor::Visit(ConstDeclaration* decl) {
     153             :   Declarations::DeclareNamespaceConstant(
     154          40 :       decl->name, Declarations::GetType(decl->type), decl->expression);
     155          40 : }
     156             : 
     157         649 : void DeclarationVisitor::Visit(StandardDeclaration* decl) {
     158        1298 :   Signature signature = MakeSignature(decl->callable->signature.get());
     159         649 :   Visit(decl->callable, signature, decl->body);
     160         649 : }
     161             : 
     162           0 : void DeclarationVisitor::Visit(GenericDeclaration* decl) {
     163          48 :   Declarations::DeclareGeneric(decl->callable->name, decl);
     164           0 : }
     165             : 
     166          17 : static Statement* WrapBodyWithNoThrow(Statement* body, std::string reason) {
     167             :   return MakeNode<ExpressionStatement>(MakeNode<TryLabelExpression>(
     168             :       true, MakeNode<StatementExpression>(body),
     169             :       MakeNode<LabelBlock>("_catch", ParameterList{},
     170          51 :                            MakeNode<DebugStatement>(reason, true))));
     171             : }
     172             : 
     173         131 : void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
     174         131 :   if ((decl->body != nullptr) == decl->external) {
     175           0 :     std::stringstream stream;
     176           0 :     stream << "specialization of " << decl->name
     177           0 :            << " must either be marked 'extern' or have a body";
     178           0 :     ReportError(stream.str());
     179             :   }
     180             : 
     181         131 :   std::vector<Generic*> generic_list = Declarations::LookupGeneric(decl->name);
     182             :   // Find the matching generic specialization based on the concrete parameter
     183             :   // list.
     184         131 :   Generic* matching_generic = nullptr;
     185         262 :   Signature signature_with_types = MakeSignature(decl->signature.get());
     186         401 :   for (Generic* generic : generic_list) {
     187             :     Signature generic_signature_with_types = MakeSpecializedSignature(
     188         278 :         SpecializationKey{generic, GetTypeVector(decl->generic_parameters)});
     189         139 :     if (signature_with_types.HasSameTypesAs(generic_signature_with_types,
     190             :                                             ParameterMode::kIgnoreImplicit)) {
     191         131 :       if (matching_generic != nullptr) {
     192           0 :         std::stringstream stream;
     193           0 :         stream << "specialization of " << decl->name
     194           0 :                << " is ambigous, it matches more than one generic declaration ("
     195           0 :                << *matching_generic << " and " << *generic << ")";
     196           0 :         ReportError(stream.str());
     197             :       }
     198             :       matching_generic = generic;
     199             :     }
     200         139 :   }
     201             : 
     202         131 :   if (matching_generic == nullptr) {
     203           0 :     std::stringstream stream;
     204           0 :     if (generic_list.size() == 0) {
     205           0 :       stream << "no generic defined with the name " << decl->name;
     206           0 :       ReportError(stream.str());
     207             :     }
     208           0 :     stream << "specialization of " << decl->name
     209           0 :            << " doesn't match any generic declaration\n";
     210           0 :     stream << "specialization signature:";
     211           0 :     stream << "\n  " << signature_with_types;
     212           0 :     stream << "\ncandidates are:";
     213           0 :     for (Generic* generic : generic_list) {
     214           0 :       stream << "\n  "
     215             :              << MakeSpecializedSignature(SpecializationKey{
     216           0 :                     generic, GetTypeVector(decl->generic_parameters)});
     217             :     }
     218           0 :     ReportError(stream.str());
     219             :   }
     220             : 
     221             :   Specialize(SpecializationKey{matching_generic,
     222             :                                GetTypeVector(decl->generic_parameters)},
     223             :              matching_generic->declaration()->callable, decl->signature.get(),
     224         262 :              decl->body);
     225         131 : }
     226             : 
     227          70 : void DeclarationVisitor::Visit(ExternConstDeclaration* decl) {
     228          70 :   const Type* type = Declarations::GetType(decl->type);
     229          70 :   if (!type->IsConstexpr()) {
     230           0 :     std::stringstream stream;
     231           0 :     stream << "extern constants must have constexpr type, but found: \""
     232           0 :            << *type << "\"\n";
     233           0 :     ReportError(stream.str());
     234             :   }
     235             : 
     236         140 :   Declarations::DeclareExternConstant(decl->name, type, decl->literal);
     237          70 : }
     238             : 
     239          17 : void DeclarationVisitor::DeclareMethods(
     240             :     AggregateType* container_type, const std::vector<Declaration*>& methods) {
     241             :   // Declare the class' methods
     242             :   IdentifierExpression* constructor_this = MakeNode<IdentifierExpression>(
     243          17 :       std::vector<std::string>{}, kThisParameterName);
     244          38 :   for (auto declaration : methods) {
     245             :     StandardDeclaration* standard_declaration =
     246             :         StandardDeclaration::DynamicCast(declaration);
     247             :     DCHECK(standard_declaration);
     248             :     TorqueMacroDeclaration* method =
     249           4 :         TorqueMacroDeclaration::DynamicCast(standard_declaration->callable);
     250           4 :     Signature signature = MakeSignature(method->signature.get());
     251             :     signature.parameter_names.insert(signature.parameter_names.begin(),
     252           8 :                                      kThisParameterName);
     253             :     signature.parameter_types.types.insert(
     254           8 :         signature.parameter_types.types.begin(), container_type);
     255           4 :     signature.implicit_count++;
     256           4 :     Statement* body = *(standard_declaration->body);
     257           4 :     std::string method_name(method->name);
     258           4 :     if (method->name == kConstructMethodName) {
     259             :       // Constructor
     260           1 :       if (!signature.return_type->IsVoid()) {
     261           0 :         ReportError("constructors musn't have a return type");
     262             :       }
     263           2 :       if (signature.labels.size() != 0) {
     264           0 :         ReportError("constructors musn't have labels");
     265             :       }
     266             :       method_name = kConstructMethodName;
     267           1 :       signature.return_type = container_type;
     268             :       ReturnStatement* return_statement = MakeNode<ReturnStatement>(
     269           1 :           MakeNode<IdentifierExpression>(kThisParameterName));
     270             :       body = MakeNode<BlockStatement>(
     271           3 :           false, std::vector<Statement*>{body, return_statement});
     272           2 :       body = WrapBodyWithNoThrow(body, "exception thrown from constructor");
     273             :     }
     274             :     Declarations::CreateMethod(container_type, method_name, signature, false,
     275           4 :                                body);
     276           4 :   }
     277             : 
     278          35 :   if (container_type->Constructors().size() != 0) return;
     279             : 
     280             :   // Generate default constructor.
     281             :   Signature constructor_signature;
     282          16 :   constructor_signature.parameter_types.var_args = false;
     283          16 :   constructor_signature.return_type = container_type;
     284          16 :   std::vector<const AggregateType*> hierarchy = container_type->GetHierarchy();
     285             : 
     286             :   std::vector<Statement*> statements;
     287             :   std::vector<Statement*> initializer_statements;
     288             : 
     289             :   size_t parameter_number = 0;
     290          32 :   constructor_signature.parameter_names.push_back(kThisParameterName);
     291          32 :   constructor_signature.parameter_types.types.push_back(container_type);
     292          16 :   constructor_signature.implicit_count = 1;
     293             :   std::vector<Expression*> super_arguments;
     294          60 :   for (auto current_type : hierarchy) {
     295         105 :     for (auto& f : current_type->fields()) {
     296          98 :       std::string parameter_name("p" + std::to_string(parameter_number++));
     297          49 :       constructor_signature.parameter_names.push_back(parameter_name);
     298             :       constructor_signature.parameter_types.types.push_back(
     299          49 :           f.name_and_type.type);
     300             :       IdentifierExpression* value = MakeNode<IdentifierExpression>(
     301         147 :           std::vector<std::string>{}, parameter_name);
     302          49 :       if (container_type != current_type) {
     303             :         super_arguments.push_back(MakeNode<IdentifierExpression>(
     304          48 :             std::vector<std::string>{}, parameter_name));
     305          37 :       } else if (container_type->IsClassType()) {
     306             :         Statement* statement =
     307             :             MakeNode<ExpressionStatement>(MakeNode<StoreObjectFieldExpression>(
     308          24 :                 constructor_this, f.name_and_type.name, value));
     309          12 :         initializer_statements.push_back(statement);
     310             :       } else {
     311             :         DCHECK(container_type->IsStructType());
     312             :         LocationExpression* location = MakeNode<FieldAccessExpression>(
     313          50 :             constructor_this, f.name_and_type.name);
     314             :         Statement* statement = MakeNode<ExpressionStatement>(
     315          25 :             MakeNode<AssignmentExpression>(location, base::nullopt, value));
     316          25 :         initializer_statements.push_back(statement);
     317             :       }
     318             :     }
     319             :   }
     320             : 
     321          32 :   if (hierarchy.size() > 1) {
     322             :     IdentifierExpression* super_identifier = MakeNode<IdentifierExpression>(
     323           5 :         std::vector<std::string>{}, kSuperMethodName);
     324             :     Statement* super_call_statement =
     325             :         MakeNode<ExpressionStatement>(MakeNode<CallMethodExpression>(
     326             :             constructor_this, super_identifier, super_arguments,
     327          10 :             std::vector<std::string>{}));
     328           5 :     statements.push_back(super_call_statement);
     329             :   }
     330             : 
     331          69 :   for (auto s : initializer_statements) {
     332          37 :     statements.push_back(s);
     333             :   }
     334             : 
     335             :   statements.push_back(MakeNode<ReturnStatement>(MakeNode<IdentifierExpression>(
     336          32 :       std::vector<std::string>{}, kThisParameterName)));
     337             : 
     338          32 :   Statement* constructor_body = MakeNode<BlockStatement>(false, statements);
     339             : 
     340             :   constructor_body = WrapBodyWithNoThrow(constructor_body,
     341          32 :                                          "exception thrown from constructor");
     342             : 
     343             :   Declarations::CreateMethod(container_type, kConstructMethodName,
     344          48 :                              constructor_signature, false, constructor_body);
     345             : }
     346             : 
     347          10 : void DeclarationVisitor::Visit(StructDeclaration* decl) {
     348             :   std::vector<Field> fields;
     349             :   size_t offset = 0;
     350          45 :   for (auto& field : decl->fields) {
     351          25 :     const Type* field_type = Declarations::GetType(field.type);
     352          50 :     fields.push_back({{field.name, field_type}, offset, false});
     353          25 :     offset += LoweredSlotCount(field_type);
     354             :   }
     355          10 :   StructType* struct_type = Declarations::DeclareStruct(decl->name, fields);
     356          10 :   DeclareMethods(struct_type, decl->methods);
     357          10 : }
     358             : 
     359           7 : void DeclarationVisitor::Visit(ClassDeclaration* decl) {
     360             :   // Compute the offset of the class' first member. If the class extends
     361             :   // another class, it's the size of the extended class, otherwise zero.
     362             :   size_t first_field_offset = 0;
     363           7 :   if (decl->extends) {
     364          14 :     const Type* super_type = Declarations::LookupType(*decl->extends);
     365           7 :     if (super_type != TypeOracle::GetTaggedType()) {
     366           6 :       const ClassType* super_class = ClassType::DynamicCast(super_type);
     367           6 :       if (!super_class) {
     368             :         ReportError(
     369             :             "class \"", decl->name,
     370           0 :             "\" must extend either Tagged or an already declared class");
     371             :       }
     372             :       first_field_offset = super_class->size();
     373             :     }
     374             :   }
     375             : 
     376             :   // The generates clause must create a TNode<>
     377           7 :   std::string generates = decl->name;
     378           7 :   if (decl->generates) {
     379           0 :     if (generates.length() < 7 || generates.substr(0, 6) != "TNode<" ||
     380           0 :         generates.substr(generates.length() - 1, 1) != ">") {
     381             :       ReportError("generated type \"", generates,
     382           0 :                   "\" should be of the form \"TNode<...>\"");
     383             :     }
     384           0 :     generates = generates.substr(6, generates.length() - 7);
     385             :   }
     386             : 
     387           7 :   std::vector<Field> fields;
     388             :   size_t offset = first_field_offset;
     389             :   bool seen_strong = false;
     390             :   bool seen_weak = false;
     391          27 :   for (ClassFieldExpression& field : decl->fields) {
     392          13 :     const Type* field_type = Declarations::GetType(field.name_and_type.type);
     393          13 :     if (field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
     394          13 :       if (field.weak) {
     395             :         seen_weak = true;
     396             :       } else {
     397          11 :         if (seen_weak) {
     398             :           ReportError("cannot declare strong field \"",
     399             :                       field.name_and_type.name,
     400           0 :                       "\" after weak Tagged references");
     401             :         }
     402             :         seen_strong = true;
     403             :       }
     404             :     } else {
     405           0 :       if (seen_strong || seen_weak) {
     406             :         ReportError("cannot declare scalar field \"", field.name_and_type.name,
     407           0 :                     "\" after strong or weak Tagged references");
     408             :       }
     409             :     }
     410          13 :     if (!field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
     411             :       ReportError(
     412             :           "field \"", field.name_and_type.name, "\" of class \"", decl->name,
     413           0 :           "\" must be a subtype of Tagged (other types not yet supported)");
     414             :     }
     415             :     fields.push_back(
     416          26 :         {{field.name_and_type.name, field_type}, offset, field.weak});
     417          13 :     offset += kTaggedSize;
     418             :   }
     419             : 
     420             :   auto new_class = Declarations::DeclareClass(
     421          21 :       decl->extends, decl->name, decl->transient, generates, fields, offset);
     422           7 :   DeclareMethods(new_class, decl->methods);
     423             : 
     424             :   // For each field, construct AST snippits that implement a CSA accessor
     425             :   // function and define a corresponding '.field' operator. The
     426             :   // implementation iterator will turn the snippits into code.
     427          27 :   for (auto& field : new_class->fields()) {
     428             :     IdentifierExpression* parameter =
     429          26 :         MakeNode<IdentifierExpression>(std::string{"o"});
     430             : 
     431             :     // Load accessor
     432          13 :     std::string camel_field_name = CamelifyString(field.name_and_type.name);
     433          26 :     std::string load_macro_name = "Load" + new_class->name() + camel_field_name;
     434          13 :     std::string load_operator_name = "." + field.name_and_type.name;
     435          13 :     Signature load_signature;
     436          26 :     load_signature.parameter_names.push_back("o");
     437          26 :     load_signature.parameter_types.types.push_back(new_class);
     438          13 :     load_signature.parameter_types.var_args = false;
     439          13 :     load_signature.return_type = field.name_and_type.type;
     440             :     Statement* load_body =
     441             :         MakeNode<ReturnStatement>(MakeNode<LoadObjectFieldExpression>(
     442          26 :             parameter, field.name_and_type.name));
     443             :     Declarations::DeclareMacro(load_macro_name, base::nullopt, load_signature,
     444          39 :                                false, load_body, load_operator_name);
     445             : 
     446             :     // Store accessor
     447             :     IdentifierExpression* value = MakeNode<IdentifierExpression>(
     448          39 :         std::vector<std::string>{}, std::string{"v"});
     449             :     std::string store_macro_name =
     450          26 :         "Store" + new_class->name() + camel_field_name;
     451          26 :     std::string store_operator_name = "." + field.name_and_type.name + "=";
     452          13 :     Signature store_signature;
     453          26 :     store_signature.parameter_names.push_back("o");
     454          26 :     store_signature.parameter_names.push_back("v");
     455          26 :     store_signature.parameter_types.types.push_back(new_class);
     456          13 :     store_signature.parameter_types.types.push_back(field.name_and_type.type);
     457          13 :     store_signature.parameter_types.var_args = false;
     458             :     // TODO(danno): Store macros probably should return their value argument
     459          13 :     store_signature.return_type = TypeOracle::GetVoidType();
     460             :     Statement* store_body =
     461             :         MakeNode<ExpressionStatement>(MakeNode<StoreObjectFieldExpression>(
     462          26 :             parameter, field.name_and_type.name, value));
     463             :     Declarations::DeclareMacro(store_macro_name, base::nullopt, store_signature,
     464          39 :                                false, store_body, store_operator_name);
     465             :   }
     466             : 
     467           7 :   GlobalContext::RegisterClass(decl->name, new_class);
     468           7 : }
     469             : 
     470          13 : void DeclarationVisitor::Visit(CppIncludeDeclaration* decl) {
     471          26 :   GlobalContext::AddCppInclude(decl->include_path);
     472          13 : }
     473             : 
     474          84 : void DeclarationVisitor::Visit(TypeDeclaration* decl) {
     475          84 :   std::string generates = decl->generates ? *decl->generates : std::string("");
     476          84 :   if (decl->generates) {
     477         290 :     if (generates.length() < 7 || generates.substr(0, 6) != "TNode<" ||
     478         174 :         generates.substr(generates.length() - 1, 1) != ">") {
     479             :       ReportError("generated type \"", generates,
     480           0 :                   "\" should be of the form \"TNode<...>\"");
     481             :     }
     482         116 :     generates = generates.substr(6, generates.length() - 7);
     483             :   }
     484             : 
     485             :   const AbstractType* type = Declarations::DeclareAbstractType(
     486         199 :       decl->name, decl->transient, generates, {}, decl->extends);
     487             : 
     488          84 :   if (decl->constexpr_generates) {
     489          31 :     if (decl->transient) {
     490           0 :       ReportError("cannot declare a transient type that is also constexpr");
     491             :     }
     492          31 :     std::string constexpr_name = CONSTEXPR_TYPE_PREFIX + decl->name;
     493          31 :     base::Optional<std::string> constexpr_extends;
     494          31 :     if (decl->extends)
     495          16 :       constexpr_extends = CONSTEXPR_TYPE_PREFIX + *decl->extends;
     496             :     Declarations::DeclareAbstractType(constexpr_name, false,
     497          31 :                                       *decl->constexpr_generates, type,
     498          31 :                                       constexpr_extends);
     499             :   }
     500          84 : }
     501             : 
     502        2330 : void DeclarationVisitor::DeclareSpecializedTypes(const SpecializationKey& key) {
     503             :   size_t i = 0;
     504             :   const std::size_t generic_parameter_count =
     505        6026 :       key.generic->declaration()->generic_parameters.size();
     506        4660 :   if (generic_parameter_count != key.specialized_types.size()) {
     507           0 :     std::stringstream stream;
     508           0 :     stream << "Wrong generic argument count for specialization of \""
     509           0 :            << key.generic->name() << "\", expected: " << generic_parameter_count
     510           0 :            << ", actual: " << key.specialized_types.size();
     511           0 :     ReportError(stream.str());
     512             :   }
     513             : 
     514        9722 :   for (auto type : key.specialized_types) {
     515             :     std::string generic_type_name =
     516       11088 :         key.generic->declaration()->generic_parameters[i++];
     517        3696 :     Declarations::DeclareType(generic_type_name, type, true);
     518             :   }
     519        2330 : }
     520             : 
     521        2159 : Signature DeclarationVisitor::MakeSpecializedSignature(
     522             :     const SpecializationKey& key) {
     523        4318 :   CurrentScope::Scope generic_scope(key.generic->ParentScope());
     524             :   // Create a temporary fake-namespace just to temporarily declare the
     525             :   // specialization aliases for the generic types to create a signature.
     526        6477 :   Namespace tmp_namespace("_tmp");
     527        2159 :   CurrentScope::Scope tmp_namespace_scope(&tmp_namespace);
     528        2159 :   DeclareSpecializedTypes(key);
     529        8636 :   return MakeSignature(key.generic->declaration()->callable->signature.get());
     530             : }
     531             : 
     532         171 : Callable* DeclarationVisitor::SpecializeImplicit(const SpecializationKey& key) {
     533         391 :   if (!key.generic->declaration()->body &&
     534          49 :       IntrinsicDeclaration::DynamicCast(key.generic->declaration()->callable) ==
     535             :           nullptr) {
     536           0 :     ReportError("missing specialization of ", key.generic->name(),
     537             :                 " with types <", key.specialized_types, "> declared at ",
     538           0 :                 key.generic->pos());
     539             :   }
     540         171 :   CurrentScope::Scope generic_scope(key.generic->ParentScope());
     541             :   Callable* result =
     542             :       Specialize(key, key.generic->declaration()->callable, base::nullopt,
     543         342 :                  key.generic->declaration()->body);
     544         171 :   CurrentScope::Scope callable_scope(result);
     545         171 :   DeclareSpecializedTypes(key);
     546         342 :   return result;
     547             : }
     548             : 
     549         302 : Callable* DeclarationVisitor::Specialize(
     550             :     const SpecializationKey& key, CallableNode* declaration,
     551         302 :     base::Optional<const CallableNodeSignature*> signature,
     552             :     base::Optional<Statement*> body) {
     553             :   // TODO(tebbi): The error should point to the source position where the
     554             :   // instantiation was requested.
     555         604 :   CurrentSourcePosition::Scope pos_scope(key.generic->declaration()->pos);
     556             :   size_t generic_parameter_count =
     557         604 :       key.generic->declaration()->generic_parameters.size();
     558         604 :   if (generic_parameter_count != key.specialized_types.size()) {
     559           0 :     std::stringstream stream;
     560           0 :     stream << "number of template parameters ("
     561           0 :            << std::to_string(key.specialized_types.size())
     562           0 :            << ") to intantiation of generic " << declaration->name
     563           0 :            << " doesnt match the generic's declaration ("
     564           0 :            << std::to_string(generic_parameter_count) << ")";
     565           0 :     ReportError(stream.str());
     566             :   }
     567         302 :   if (key.generic->GetSpecialization(key.specialized_types)) {
     568           0 :     ReportError("cannot redeclare specialization of ", key.generic->name(),
     569           0 :                 " with types <", key.specialized_types, ">");
     570             :   }
     571             : 
     572             :   Signature type_signature =
     573         604 :       signature ? MakeSignature(*signature) : MakeSpecializedSignature(key);
     574             : 
     575             :   std::string generated_name = Declarations::GetGeneratedCallableName(
     576         302 :       declaration->name, key.specialized_types);
     577         604 :   std::stringstream readable_name;
     578         302 :   readable_name << declaration->name << "<";
     579             :   bool first = true;
     580         992 :   for (const Type* t : key.specialized_types) {
     581         388 :     if (!first) readable_name << ", ";
     582         388 :     readable_name << *t;
     583             :     first = false;
     584             :   }
     585         302 :   readable_name << ">";
     586             :   Callable* callable;
     587         302 :   if (MacroDeclaration::DynamicCast(declaration) != nullptr) {
     588             :     callable = Declarations::CreateMacro(generated_name, readable_name.str(),
     589             :                                          base::nullopt, type_signature,
     590         985 :                                          declaration->transitioning, *body);
     591         105 :   } else if (IntrinsicDeclaration::DynamicCast(declaration) != nullptr) {
     592          49 :     callable = Declarations::CreateIntrinsic(declaration->name, type_signature);
     593             :   } else {
     594             :     BuiltinDeclaration* builtin = BuiltinDeclaration::cast(declaration);
     595             :     callable = CreateBuiltin(builtin, generated_name, readable_name.str(),
     596         224 :                              type_signature, *body);
     597             :   }
     598         302 :   key.generic->AddSpecialization(key.specialized_types, callable);
     599         302 :   return callable;
     600             : }
     601             : 
     602             : }  // namespace torque
     603             : }  // namespace internal
     604        9078 : }  // namespace v8

Generated by: LCOV version 1.10