LCOV - code coverage report
Current view: top level - src/torque - declaration-visitor.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 269 368 73.1 %
Date: 2019-02-19 Functions: 25 27 92.6 %

          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        1176 : void DeclarationVisitor::Visit(Declaration* decl) {
      13        1176 :   CurrentSourcePosition::Scope scope(decl->pos);
      14        1176 :   switch (decl->kind) {
      15             : #define ENUM_ITEM(name)        \
      16             :   case AstNode::Kind::k##name: \
      17             :     return Visit(name::cast(decl));
      18        1126 :     AST_DECLARATION_NODE_KIND_LIST(ENUM_ITEM)
      19             : #undef ENUM_ITEM
      20             :     default:
      21           0 :       UNIMPLEMENTED();
      22             :   }
      23             : }
      24             : 
      25         705 : void DeclarationVisitor::Visit(CallableNode* decl, const Signature& signature,
      26             :                                base::Optional<Statement*> body) {
      27         705 :   switch (decl->kind) {
      28             : #define ENUM_ITEM(name)        \
      29             :   case AstNode::Kind::k##name: \
      30             :     return Visit(name::cast(decl), signature, body);
      31         705 :     AST_CALLABLE_NODE_KIND_LIST(ENUM_ITEM)
      32             : #undef ENUM_ITEM
      33             :     default:
      34           0 :       UNIMPLEMENTED();
      35             :   }
      36             : }
      37             : 
      38         150 : Builtin* DeclarationVisitor::CreateBuiltin(BuiltinDeclaration* decl,
      39             :                                            std::string external_name,
      40             :                                            std::string readable_name,
      41             :                                            Signature signature,
      42             :                                            base::Optional<Statement*> body) {
      43         150 :   const bool javascript = decl->javascript_linkage;
      44         150 :   const bool varargs = decl->signature->parameters.has_varargs;
      45             :   Builtin::Kind kind = !javascript ? Builtin::kStub
      46             :                                    : varargs ? Builtin::kVarArgsJavaScript
      47         150 :                                              : Builtin::kFixedArgsJavaScript;
      48             : 
      49         600 :   if (signature.types().size() == 0 ||
      50             :       !(signature.types()[0] ==
      51         600 :         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         150 :   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         150 :   if (javascript) {
      66         232 :     if (signature.types().size() < 2 ||
      67             :         !(signature.types()[1] ==
      68         232 :           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        1328 :   for (size_t i = 0; i < signature.types().size(); ++i) {
      77         514 :     if (const StructType* type =
      78         514 :             StructType::DynamicCast(signature.types()[i])) {
      79           0 :       std::stringstream stream;
      80           0 :       stream << "builtin '" << decl->name << "' uses the struct '"
      81           0 :              << type->name() << "' as argument '"
      82           0 :              << signature.parameter_names[i] << "'. This is not supported.";
      83           0 :       ReportError(stream.str());
      84             :     }
      85             :   }
      86             : 
      87         150 :   if (const StructType* struct_type =
      88         150 :           StructType::DynamicCast(signature.return_type)) {
      89           0 :     std::stringstream stream;
      90           0 :     stream << "builtins (in this case " << decl->name
      91           0 :            << ") cannot return structs (in this case " << struct_type->name()
      92           0 :            << ")";
      93           0 :     ReportError(stream.str());
      94             :   }
      95             : 
      96             :   return Declarations::CreateBuiltin(
      97             :       std::move(external_name), std::move(readable_name), kind,
      98         600 :       std::move(signature), decl->transitioning, body);
      99             : }
     100             : 
     101          14 : void DeclarationVisitor::Visit(ExternalRuntimeDeclaration* decl,
     102             :                                const Signature& signature,
     103             :                                base::Optional<Statement*> body) {
     104          14 :   if (GlobalContext::verbose()) {
     105           0 :     std::cout << "found declaration of external runtime " << decl->name
     106           0 :               << " with signature ";
     107             :   }
     108             : 
     109          56 :   if (signature.parameter_types.types.size() == 0 ||
     110             :       !(signature.parameter_types.types[0] ==
     111          56 :         Declarations::LookupGlobalType(CONTEXT_TYPE_STRING))) {
     112           0 :     std::stringstream stream;
     113           0 :     stream << "first parameter to runtime " << decl->name
     114           0 :            << " is not a context but should be";
     115           0 :     ReportError(stream.str());
     116             :   }
     117             : 
     118          28 :   if (signature.return_type->IsStructType()) {
     119           0 :     std::stringstream stream;
     120           0 :     stream << "runtime functions (in this case" << decl->name
     121           0 :            << ") cannot return structs (in this case "
     122           0 :            << static_cast<const StructType*>(signature.return_type)->name()
     123           0 :            << ")";
     124           0 :     ReportError(stream.str());
     125             :   }
     126             : 
     127             :   Declarations::DeclareRuntimeFunction(decl->name, signature,
     128          14 :                                        decl->transitioning);
     129          14 : }
     130             : 
     131         393 : void DeclarationVisitor::Visit(ExternalMacroDeclaration* decl,
     132             :                                const Signature& signature,
     133             :                                base::Optional<Statement*> body) {
     134         393 :   if (GlobalContext::verbose()) {
     135           0 :     std::cout << "found declaration of external macro " << decl->name
     136           0 :               << " with signature ";
     137             :   }
     138             : 
     139             :   Declarations::DeclareMacro(decl->name, decl->external_assembler_name,
     140        1572 :                              signature, decl->transitioning, body, decl->op);
     141         393 : }
     142             : 
     143          78 : void DeclarationVisitor::Visit(TorqueBuiltinDeclaration* decl,
     144             :                                const Signature& signature,
     145             :                                base::Optional<Statement*> body) {
     146             :   Declarations::Declare(
     147         234 :       decl->name, CreateBuiltin(decl, decl->name, decl->name, signature, body));
     148          78 : }
     149             : 
     150         202 : void DeclarationVisitor::Visit(TorqueMacroDeclaration* decl,
     151             :                                const Signature& signature,
     152             :                                base::Optional<Statement*> body) {
     153             :   Declarations::DeclareMacro(decl->name, base::nullopt, signature,
     154         808 :                              decl->transitioning, body, decl->op);
     155         202 : }
     156             : 
     157           0 : void DeclarationVisitor::Visit(IntrinsicDeclaration* decl,
     158             :                                const Signature& signature,
     159             :                                base::Optional<Statement*> body) {
     160           0 :   Declarations::DeclareIntrinsic(decl->name, signature);
     161           0 : }
     162             : 
     163          24 : void DeclarationVisitor::Visit(ConstDeclaration* decl) {
     164             :   Declarations::DeclareNamespaceConstant(
     165          24 :       decl->name, Declarations::GetType(decl->type), decl->expression);
     166          24 : }
     167             : 
     168         705 : void DeclarationVisitor::Visit(StandardDeclaration* decl) {
     169        1410 :   Signature signature = MakeSignature(decl->callable->signature.get());
     170         705 :   Visit(decl->callable, signature, decl->body);
     171         705 : }
     172             : 
     173           0 : void DeclarationVisitor::Visit(GenericDeclaration* decl) {
     174          50 :   Declarations::DeclareGeneric(decl->callable->name, decl);
     175           0 : }
     176             : 
     177         138 : void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
     178         138 :   if ((decl->body != nullptr) == decl->external) {
     179           0 :     std::stringstream stream;
     180           0 :     stream << "specialization of " << decl->name
     181           0 :            << " must either be marked 'extern' or have a body";
     182           0 :     ReportError(stream.str());
     183             :   }
     184             : 
     185         138 :   std::vector<Generic*> generic_list = Declarations::LookupGeneric(decl->name);
     186             :   // Find the matching generic specialization based on the concrete parameter
     187             :   // list.
     188         138 :   Generic* matching_generic = nullptr;
     189         276 :   Signature signature_with_types = MakeSignature(decl->signature.get());
     190         445 :   for (Generic* generic : generic_list) {
     191             :     Signature generic_signature_with_types = MakeSpecializedSignature(
     192         338 :         SpecializationKey{generic, GetTypeVector(decl->generic_parameters)});
     193         169 :     if (signature_with_types.HasSameTypesAs(generic_signature_with_types,
     194             :                                             ParameterMode::kIgnoreImplicit)) {
     195         138 :       if (matching_generic != nullptr) {
     196           0 :         std::stringstream stream;
     197           0 :         stream << "specialization of " << decl->name
     198           0 :                << " is ambigous, it matches more than one generic declaration ("
     199           0 :                << *matching_generic << " and " << *generic << ")";
     200           0 :         ReportError(stream.str());
     201             :       }
     202             :       matching_generic = generic;
     203             :     }
     204         169 :   }
     205             : 
     206         138 :   if (matching_generic == nullptr) {
     207           0 :     std::stringstream stream;
     208           0 :     if (generic_list.size() == 0) {
     209           0 :       stream << "no generic defined with the name " << decl->name;
     210           0 :       ReportError(stream.str());
     211             :     }
     212           0 :     stream << "specialization of " << decl->name
     213           0 :            << " doesn't match any generic declaration\n";
     214           0 :     stream << "specialization signature:";
     215           0 :     stream << "\n  " << signature_with_types;
     216           0 :     stream << "\ncandidates are:";
     217           0 :     for (Generic* generic : generic_list) {
     218           0 :       stream << "\n  "
     219             :              << MakeSpecializedSignature(SpecializationKey{
     220           0 :                     generic, GetTypeVector(decl->generic_parameters)});
     221             :     }
     222           0 :     ReportError(stream.str());
     223             :   }
     224             : 
     225             :   Specialize(SpecializationKey{matching_generic,
     226             :                                GetTypeVector(decl->generic_parameters)},
     227             :              matching_generic->declaration()->callable, decl->signature.get(),
     228         276 :              decl->body);
     229         138 : }
     230             : 
     231          81 : void DeclarationVisitor::Visit(ExternConstDeclaration* decl) {
     232          81 :   const Type* type = Declarations::GetType(decl->type);
     233          81 :   if (!type->IsConstexpr()) {
     234           0 :     std::stringstream stream;
     235           0 :     stream << "extern constants must have constexpr type, but found: \""
     236           0 :            << *type << "\"\n";
     237           0 :     ReportError(stream.str());
     238             :   }
     239             : 
     240         162 :   Declarations::DeclareExternConstant(decl->name, type, decl->literal);
     241          81 : }
     242             : 
     243          32 : void DeclarationVisitor::DeclareMethods(
     244             :     AggregateType* container_type, const std::vector<Declaration*>& methods) {
     245             :   // Declare the class' methods
     246             :   IdentifierExpression* constructor_this = MakeNode<IdentifierExpression>(
     247          32 :       std::vector<std::string>{}, kThisParameterName);
     248             :   AggregateType* constructor_this_type =
     249             :       container_type->IsStructType()
     250             :           ? container_type
     251          32 :           : ClassType::cast(container_type)->struct_type();
     252          87 :   for (auto declaration : methods) {
     253          23 :     CurrentSourcePosition::Scope pos_scope(declaration->pos);
     254             :     StandardDeclaration* standard_declaration =
     255             :         StandardDeclaration::DynamicCast(declaration);
     256             :     DCHECK(standard_declaration);
     257             :     TorqueMacroDeclaration* method =
     258          23 :         TorqueMacroDeclaration::DynamicCast(standard_declaration->callable);
     259          46 :     Signature signature = MakeSignature(method->signature.get());
     260             :     signature.parameter_names.insert(
     261             :         signature.parameter_names.begin() + signature.implicit_count,
     262          46 :         kThisParameterName);
     263          23 :     Statement* body = *(standard_declaration->body);
     264          23 :     std::string method_name(method->name);
     265          23 :     if (method->name == kConstructMethodName) {
     266             :       signature.parameter_types.types.insert(
     267             :           signature.parameter_types.types.begin() + signature.implicit_count,
     268          20 :           constructor_this_type);
     269             :       // Constructor
     270          10 :       if (!signature.return_type->IsVoid()) {
     271           0 :         ReportError("constructors musn't have a return type");
     272             :       }
     273          20 :       if (signature.labels.size() != 0) {
     274           0 :         ReportError("constructors musn't have labels");
     275             :       }
     276             :       method_name = kConstructMethodName;
     277             :       Declarations::CreateMethod(constructor_this_type, method_name, signature,
     278          10 :                                  false, body);
     279             :     } else {
     280             :       signature.parameter_types.types.insert(
     281             :           signature.parameter_types.types.begin() + signature.implicit_count,
     282          26 :           container_type);
     283             :       Declarations::CreateMethod(container_type, method_name, signature, false,
     284          13 :                                  body);
     285             :     }
     286             :   }
     287             : 
     288          75 :   if (constructor_this_type->Constructors().size() != 0) return;
     289             : 
     290             :   // TODO(danno): Currently, default constructors for classes with
     291             :   // open-ended arrays at the end are not supported. For now, if one is
     292             :   // encountered, don't actually create the constructor.
     293          24 :   if (container_type->HasIndexedField()) return;
     294             : 
     295             :   // Generate default constructor.
     296             :   Signature constructor_signature;
     297          21 :   constructor_signature.parameter_types.var_args = false;
     298          21 :   constructor_signature.return_type = TypeOracle::GetVoidType();
     299          21 :   std::vector<const AggregateType*> hierarchy = container_type->GetHierarchy();
     300             : 
     301             :   std::vector<Statement*> statements;
     302             :   std::vector<Statement*> initializer_statements;
     303             : 
     304             :   size_t parameter_number = 0;
     305          42 :   constructor_signature.parameter_names.push_back(kThisParameterName);
     306          42 :   constructor_signature.parameter_types.types.push_back(constructor_this_type);
     307             :   std::vector<Expression*> super_arguments;
     308          90 :   for (auto current_type : hierarchy) {
     309         195 :     for (auto& f : current_type->fields()) {
     310             :       DCHECK(!f.index);
     311         198 :       std::string parameter_name("p" + std::to_string(parameter_number++));
     312          99 :       constructor_signature.parameter_names.push_back(parameter_name);
     313             :       constructor_signature.parameter_types.types.push_back(
     314          99 :           f.name_and_type.type);
     315             :       IdentifierExpression* value = MakeNode<IdentifierExpression>(
     316         297 :           std::vector<std::string>{}, parameter_name);
     317          99 :       if (container_type != current_type) {
     318             :         super_arguments.push_back(MakeNode<IdentifierExpression>(
     319         152 :             std::vector<std::string>{}, parameter_name));
     320             :       } else {
     321             :         LocationExpression* location = MakeNode<FieldAccessExpression>(
     322         122 :             constructor_this, f.name_and_type.name);
     323             :         Statement* statement = MakeNode<ExpressionStatement>(
     324          61 :             MakeNode<AssignmentExpression>(location, base::nullopt, value));
     325          61 :         initializer_statements.push_back(statement);
     326             :       }
     327             :     }
     328             :   }
     329             : 
     330          42 :   if (hierarchy.size() > 1) {
     331             :     IdentifierExpression* super_identifier = MakeNode<IdentifierExpression>(
     332          11 :         std::vector<std::string>{}, kSuperMethodName);
     333             :     Statement* statement =
     334             :         MakeNode<ExpressionStatement>(MakeNode<CallMethodExpression>(
     335             :             constructor_this, super_identifier, super_arguments,
     336          22 :             std::vector<std::string>{}));
     337          11 :     statements.push_back(statement);
     338             :   }
     339             : 
     340         103 :   for (auto s : initializer_statements) {
     341          61 :     statements.push_back(s);
     342             :   }
     343             : 
     344          42 :   Statement* constructor_body = MakeNode<BlockStatement>(false, statements);
     345             : 
     346             :   Declarations::CreateMethod(constructor_this_type, kConstructMethodName,
     347          63 :                              constructor_signature, false, constructor_body);
     348             : }
     349             : 
     350          13 : void DeclarationVisitor::Visit(StructDeclaration* decl) {
     351          13 :   StructType* struct_type = Declarations::DeclareStruct(decl->name);
     352             :   struct_declarations_.push_back(
     353          26 :       std::make_tuple(CurrentScope::Get(), decl, struct_type));
     354          13 : }
     355             : 
     356          19 : void DeclarationVisitor::Visit(ClassDeclaration* decl) {
     357             :   ClassType* new_class;
     358          19 :   if (decl->is_extern) {
     359          19 :     if (!decl->super) {
     360           0 :       ReportError("Extern class must extend another type.");
     361             :     }
     362             :     // Compute the offset of the class' first member. If the class extends
     363             :     // another class, it's the size of the extended class, otherwise zero.
     364          34 :     const Type* super_type = Declarations::LookupType(*decl->super);
     365          17 :     if (super_type != TypeOracle::GetTaggedType()) {
     366             :       const ClassType* super_class = ClassType::DynamicCast(super_type);
     367          16 :       if (!super_class) {
     368             :         ReportError(
     369             :             "class \"", decl->name,
     370           0 :             "\" must extend either Tagged or an already declared class");
     371             :       }
     372             :     }
     373             : 
     374             :     // The generates clause must create a TNode<>
     375          17 :     std::string generates = decl->name;
     376          19 :     if (decl->generates) {
     377           1 :       generates = *decl->generates;
     378           5 :       if (generates.length() < 7 || generates.substr(0, 6) != "TNode<" ||
     379           3 :           generates.substr(generates.length() - 1, 1) != ">") {
     380             :         ReportError("generated type \"", generates,
     381           0 :                     "\" should be of the form \"TNode<...>\"");
     382             :       }
     383           2 :       generates = generates.substr(6, generates.length() - 7);
     384             :     }
     385             : 
     386             :     new_class = Declarations::DeclareClass(
     387          17 :         super_type, decl->name, decl->is_extern, decl->transient, generates);
     388             :   } else {
     389           2 :     if (decl->super) {
     390           0 :       ReportError("Only extern classes can inherit.");
     391             :     }
     392           2 :     if (decl->generates) {
     393           0 :       ReportError("Only extern classes can specify a generated type.");
     394             :     }
     395             :     new_class = Declarations::DeclareClass(TypeOracle::GetTaggedType(),
     396             :                                            decl->name, decl->is_extern,
     397           4 :                                            decl->transient, "FixedArray");
     398             :   }
     399          19 :   GlobalContext::RegisterClass(decl->name, new_class);
     400             :   class_declarations_.push_back(
     401          38 :       std::make_tuple(CurrentScope::Get(), decl, new_class));
     402          19 : }
     403             : 
     404          15 : void DeclarationVisitor::Visit(CppIncludeDeclaration* decl) {
     405          30 :   GlobalContext::AddCppInclude(decl->include_path);
     406          15 : }
     407             : 
     408          87 : void DeclarationVisitor::Visit(TypeDeclaration* decl) {
     409          87 :   std::string generates = decl->generates ? *decl->generates : std::string("");
     410          87 :   if (decl->generates) {
     411         295 :     if (generates.length() < 7 || generates.substr(0, 6) != "TNode<" ||
     412         177 :         generates.substr(generates.length() - 1, 1) != ">") {
     413             :       ReportError("generated type \"", generates,
     414           0 :                   "\" should be of the form \"TNode<...>\"");
     415             :     }
     416         118 :     generates = generates.substr(6, generates.length() - 7);
     417             :   }
     418             : 
     419             :   const AbstractType* type = Declarations::DeclareAbstractType(
     420         210 :       decl->name, decl->transient, generates, {}, decl->extends);
     421             : 
     422          87 :   if (decl->constexpr_generates) {
     423          36 :     if (decl->transient) {
     424           0 :       ReportError("cannot declare a transient type that is also constexpr");
     425             :     }
     426          36 :     std::string constexpr_name = CONSTEXPR_TYPE_PREFIX + decl->name;
     427          36 :     base::Optional<std::string> constexpr_extends;
     428          36 :     if (decl->extends)
     429          26 :       constexpr_extends = CONSTEXPR_TYPE_PREFIX + *decl->extends;
     430             :     Declarations::DeclareAbstractType(constexpr_name, false,
     431          36 :                                       *decl->constexpr_generates, type,
     432          36 :                                       constexpr_extends);
     433             :   }
     434          87 : }
     435             : 
     436        2903 : void DeclarationVisitor::DeclareSpecializedTypes(const SpecializationKey& key) {
     437             :   size_t i = 0;
     438             :   const std::size_t generic_parameter_count =
     439        7544 :       key.generic->declaration()->generic_parameters.size();
     440        5806 :   if (generic_parameter_count != key.specialized_types.size()) {
     441           0 :     std::stringstream stream;
     442           0 :     stream << "Wrong generic argument count for specialization of \""
     443           0 :            << key.generic->name() << "\", expected: " << generic_parameter_count
     444           0 :            << ", actual: " << key.specialized_types.size();
     445           0 :     ReportError(stream.str());
     446             :   }
     447             : 
     448       12185 :   for (auto type : key.specialized_types) {
     449             :     std::string generic_type_name =
     450       13923 :         key.generic->declaration()->generic_parameters[i++];
     451        4641 :     Declarations::DeclareType(generic_type_name, type, true);
     452             :   }
     453        2903 : }
     454             : 
     455        2715 : Signature DeclarationVisitor::MakeSpecializedSignature(
     456             :     const SpecializationKey& key) {
     457        5430 :   CurrentScope::Scope generic_scope(key.generic->ParentScope());
     458             :   // Create a temporary fake-namespace just to temporarily declare the
     459             :   // specialization aliases for the generic types to create a signature.
     460        8145 :   Namespace tmp_namespace("_tmp");
     461        2715 :   CurrentScope::Scope tmp_namespace_scope(&tmp_namespace);
     462        2715 :   DeclareSpecializedTypes(key);
     463       10860 :   return MakeSignature(key.generic->declaration()->callable->signature.get());
     464             : }
     465             : 
     466         188 : Callable* DeclarationVisitor::SpecializeImplicit(const SpecializationKey& key) {
     467         442 :   if (!key.generic->declaration()->body &&
     468          66 :       IntrinsicDeclaration::DynamicCast(key.generic->declaration()->callable) ==
     469             :           nullptr) {
     470           0 :     ReportError("missing specialization of ", key.generic->name(),
     471             :                 " with types <", key.specialized_types, "> declared at ",
     472           0 :                 key.generic->pos());
     473             :   }
     474         188 :   CurrentScope::Scope generic_scope(key.generic->ParentScope());
     475             :   Callable* result =
     476             :       Specialize(key, key.generic->declaration()->callable, base::nullopt,
     477         376 :                  key.generic->declaration()->body);
     478         188 :   CurrentScope::Scope callable_scope(result);
     479         188 :   DeclareSpecializedTypes(key);
     480         376 :   return result;
     481             : }
     482             : 
     483         326 : Callable* DeclarationVisitor::Specialize(
     484             :     const SpecializationKey& key, CallableNode* declaration,
     485         326 :     base::Optional<const CallableNodeSignature*> signature,
     486             :     base::Optional<Statement*> body) {
     487             :   // TODO(tebbi): The error should point to the source position where the
     488             :   // instantiation was requested.
     489         652 :   CurrentSourcePosition::Scope pos_scope(key.generic->declaration()->pos);
     490             :   size_t generic_parameter_count =
     491         652 :       key.generic->declaration()->generic_parameters.size();
     492         652 :   if (generic_parameter_count != key.specialized_types.size()) {
     493           0 :     std::stringstream stream;
     494           0 :     stream << "number of template parameters ("
     495           0 :            << std::to_string(key.specialized_types.size())
     496           0 :            << ") to intantiation of generic " << declaration->name
     497           0 :            << " doesnt match the generic's declaration ("
     498           0 :            << std::to_string(generic_parameter_count) << ")";
     499           0 :     ReportError(stream.str());
     500             :   }
     501         326 :   if (key.generic->GetSpecialization(key.specialized_types)) {
     502           0 :     ReportError("cannot redeclare specialization of ", key.generic->name(),
     503           0 :                 " with types <", key.specialized_types, ">");
     504             :   }
     505             : 
     506             :   Signature type_signature =
     507         652 :       signature ? MakeSignature(*signature) : MakeSpecializedSignature(key);
     508             : 
     509             :   std::string generated_name = Declarations::GetGeneratedCallableName(
     510         326 :       declaration->name, key.specialized_types);
     511         652 :   std::stringstream readable_name;
     512         326 :   readable_name << declaration->name << "<";
     513             :   bool first = true;
     514        1118 :   for (const Type* t : key.specialized_types) {
     515         466 :     if (!first) readable_name << ", ";
     516         466 :     readable_name << *t;
     517             :     first = false;
     518             :   }
     519         326 :   readable_name << ">";
     520             :   Callable* callable;
     521         326 :   if (MacroDeclaration::DynamicCast(declaration) != nullptr) {
     522             :     callable = Declarations::CreateMacro(generated_name, readable_name.str(),
     523             :                                          base::nullopt, type_signature,
     524        1030 :                                          declaration->transitioning, *body);
     525         120 :   } else if (IntrinsicDeclaration::DynamicCast(declaration) != nullptr) {
     526          66 :     callable = Declarations::CreateIntrinsic(declaration->name, type_signature);
     527             :   } else {
     528             :     BuiltinDeclaration* builtin = BuiltinDeclaration::cast(declaration);
     529             :     callable = CreateBuiltin(builtin, generated_name, readable_name.str(),
     530         216 :                              type_signature, *body);
     531             :   }
     532         326 :   key.generic->AddSpecialization(key.specialized_types, callable);
     533         326 :   return callable;
     534             : }
     535             : 
     536          13 : void DeclarationVisitor::FinalizeStructFieldsAndMethods(
     537             :     StructType* struct_type, StructDeclaration* struct_declaration) {
     538             :   size_t offset = 0;
     539          63 :   for (auto& field : struct_declaration->fields) {
     540          37 :     const Type* field_type = Declarations::GetType(field.name_and_type.type);
     541             :     struct_type->RegisterField({field.name_and_type.type->pos,
     542             :                                 struct_type,
     543             :                                 base::nullopt,
     544             :                                 {field.name_and_type.name, field_type},
     545             :                                 offset,
     546         111 :                                 false});
     547          37 :     offset += LoweredSlotCount(field_type);
     548             :   }
     549          13 :   CurrentSourcePosition::Scope position_activator(struct_declaration->pos);
     550          13 :   DeclareMethods(struct_type, struct_declaration->methods);
     551          13 : }
     552             : 
     553          19 : void DeclarationVisitor::FinalizeClassFieldsAndMethods(
     554             :     ClassType* class_type, ClassDeclaration* class_declaration) {
     555          32 :   const ClassType* super_class = class_type->GetSuperClass();
     556          38 :   size_t class_offset = super_class ? super_class->size() : 0;
     557             :   bool seen_indexed_field = false;
     558          98 :   for (ClassFieldExpression& field_expression : class_declaration->fields) {
     559             :     CurrentSourcePosition::Scope position_activator(
     560          60 :         field_expression.name_and_type.type->pos);
     561             :     const Type* field_type =
     562          60 :         Declarations::GetType(field_expression.name_and_type.type);
     563          60 :     if (!class_declaration->is_extern) {
     564          17 :       if (!field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
     565           0 :         ReportError("non-extern classes do not support untagged fields");
     566             :       }
     567          17 :       if (field_expression.weak) {
     568           0 :         ReportError("non-extern classes do not support weak fields");
     569             :       }
     570             :     }
     571          60 :     if (field_expression.index) {
     572           4 :       if (seen_indexed_field ||
     573           2 :           (super_class && super_class->HasIndexedField())) {
     574             :         ReportError(
     575           0 :             "only one indexable field is currently supported per class");
     576             :       }
     577             :       seen_indexed_field = true;
     578             :       const Field* index_field =
     579           2 :           &(class_type->LookupField(*field_expression.index));
     580             :       class_type->RegisterField(
     581             :           {field_expression.name_and_type.type->pos,
     582             :            class_type,
     583             :            index_field,
     584             :            {field_expression.name_and_type.name, field_type},
     585             :            class_offset,
     586           6 :            field_expression.weak});
     587             :     } else {
     588          58 :       if (seen_indexed_field) {
     589             :         ReportError("cannot declare non-indexable field \"",
     590             :                     field_expression.name_and_type.name,
     591             :                     "\" after an indexable field "
     592           0 :                     "declaration");
     593             :       }
     594             :       const Field& field = class_type->RegisterField(
     595             :           {field_expression.name_and_type.type->pos,
     596             :            class_type,
     597             :            base::nullopt,
     598             :            {field_expression.name_and_type.name, field_type},
     599             :            class_offset,
     600         174 :            field_expression.weak});
     601             :       size_t field_size;
     602             :       std::string size_string;
     603             :       std::string machine_type;
     604         174 :       std::tie(field_size, size_string, machine_type) =
     605             :           field.GetFieldSizeInformation();
     606          58 :       size_t aligned_offset = class_offset & ~(field_size - 1);
     607          58 :       if (class_offset != aligned_offset) {
     608             :         ReportError("field ", field_expression.name_and_type.name,
     609             :                     " is not aligned to its size (", aligned_offset, " vs ",
     610           0 :                     class_offset, " for field size ", field_size, ")");
     611             :       }
     612          58 :       class_offset += field_size;
     613             :     }
     614             :   }
     615          19 :   class_type->SetSize(class_offset);
     616             : 
     617             :   StructType* this_struct_type = Declarations::DeclareStruct(
     618          38 :       kClassConstructorThisStructPrefix + class_type->name());
     619             :   size_t struct_offset = 0;
     620             :   const StructType* super_struct_type = nullptr;
     621             :   // In order to ensure "atomicity" of object allocation, a class'
     622             :   // constructors operate on a per-class internal struct rather than the class
     623             :   // directly until the constructor has successfully completed and all class
     624             :   // members are available. Create the appropriate struct type for use in the
     625             :   // class' constructors, including a '_super' field in the struct that
     626             :   // contains the values constructed by calls to super constructors.
     627          19 :   if (super_class) {
     628             :     super_struct_type = super_class->struct_type();
     629             :     this_struct_type->RegisterField(
     630             :         {CurrentSourcePosition::Get(),
     631             :          super_struct_type,
     632             :          base::nullopt,
     633             :          {kConstructorStructSuperFieldName, super_struct_type},
     634             :          struct_offset,
     635          64 :          false});
     636          16 :     struct_offset += LoweredSlotCount(super_struct_type);
     637             :   }
     638          98 :   for (auto& field : class_type->fields()) {
     639          60 :     if (field.index) continue;
     640          58 :     const Type* field_type = field.name_and_type.type;
     641             :     this_struct_type->RegisterField({field.pos,
     642             :                                      class_type,
     643             :                                      base::nullopt,
     644             :                                      {field.name_and_type.name, field_type},
     645             :                                      struct_offset,
     646         174 :                                      false});
     647          58 :     struct_offset += LoweredSlotCount(field_type);
     648             :   }
     649             :   this_struct_type->SetDerivedFrom(class_type);
     650             :   class_type->SetThisStruct(this_struct_type);
     651             : 
     652             :   // For each field, construct AST snippits that implement a CSA accessor
     653             :   // function and define a corresponding '.field' operator. The
     654             :   // implementation iterator will turn the snippits into code.
     655          98 :   for (auto& field : class_type->fields()) {
     656          62 :     if (field.index) continue;
     657          58 :     CurrentSourcePosition::Scope position_activator(field.pos);
     658             :     IdentifierExpression* parameter =
     659         116 :         MakeNode<IdentifierExpression>(std::string{"o"});
     660             : 
     661             :     // Load accessor
     662          58 :     std::string camel_field_name = CamelifyString(field.name_and_type.name);
     663             :     std::string load_macro_name =
     664         116 :         "Load" + class_type->name() + camel_field_name;
     665          58 :     std::string load_operator_name = "." + field.name_and_type.name;
     666          58 :     Signature load_signature;
     667         116 :     load_signature.parameter_names.push_back("o");
     668         116 :     load_signature.parameter_types.types.push_back(class_type);
     669          58 :     load_signature.parameter_types.var_args = false;
     670          58 :     load_signature.return_type = field.name_and_type.type;
     671             :     Statement* load_body =
     672             :         MakeNode<ReturnStatement>(MakeNode<LoadObjectFieldExpression>(
     673         116 :             parameter, field.name_and_type.name));
     674             :     Declarations::DeclareMacro(load_macro_name, base::nullopt, load_signature,
     675         174 :                                false, load_body, load_operator_name);
     676             : 
     677             :     // Store accessor
     678             :     IdentifierExpression* value = MakeNode<IdentifierExpression>(
     679         174 :         std::vector<std::string>{}, std::string{"v"});
     680             :     std::string store_macro_name =
     681         116 :         "Store" + class_type->name() + camel_field_name;
     682         116 :     std::string store_operator_name = "." + field.name_and_type.name + "=";
     683          58 :     Signature store_signature;
     684         116 :     store_signature.parameter_names.push_back("o");
     685         116 :     store_signature.parameter_names.push_back("v");
     686         116 :     store_signature.parameter_types.types.push_back(class_type);
     687          58 :     store_signature.parameter_types.types.push_back(field.name_and_type.type);
     688          58 :     store_signature.parameter_types.var_args = false;
     689             :     // TODO(danno): Store macros probably should return their value argument
     690          58 :     store_signature.return_type = TypeOracle::GetVoidType();
     691             :     Statement* store_body =
     692             :         MakeNode<ExpressionStatement>(MakeNode<StoreObjectFieldExpression>(
     693         116 :             parameter, field.name_and_type.name, value));
     694             :     Declarations::DeclareMacro(store_macro_name, base::nullopt, store_signature,
     695         174 :                                false, store_body, store_operator_name);
     696             :   }
     697             : 
     698          19 :   DeclareMethods(class_type, class_declaration->methods);
     699          19 : }
     700             : 
     701           1 : void DeclarationVisitor::FinalizeStructsAndClasses() {
     702          15 :   for (auto current_struct_info : struct_declarations_) {
     703             :     Scope* scope;
     704             :     StructDeclaration* struct_declaration;
     705             :     StructType* struct_type;
     706             :     std::tie(scope, struct_declaration, struct_type) = current_struct_info;
     707          13 :     CurrentScope::Scope scope_activator(scope);
     708          13 :     FinalizeStructFieldsAndMethods(struct_type, struct_declaration);
     709             :   }
     710             : 
     711          21 :   for (auto current_class_info : class_declarations_) {
     712             :     Scope* scope;
     713             :     ClassDeclaration* class_declaration;
     714             :     ClassType* class_type;
     715             :     std::tie(scope, class_declaration, class_type) = current_class_info;
     716          19 :     CurrentScope::Scope scope_activator(scope);
     717          19 :     CurrentSourcePosition::Scope position_activator(class_declaration->pos);
     718          19 :     FinalizeClassFieldsAndMethods(class_type, class_declaration);
     719             :   }
     720           1 : }
     721             : 
     722             : }  // namespace torque
     723             : }  // namespace internal
     724        9114 : }  // namespace v8

Generated by: LCOV version 1.10