LCOV - code coverage report
Current view: top level - src/torque - declaration-visitor.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 253 334 75.7 %
Date: 2019-04-17 Functions: 24 26 92.3 %

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

Generated by: LCOV version 1.10