LCOV - code coverage report
Current view: top level - src/torque - declaration-visitor.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 250 331 75.5 %
Date: 2019-03-21 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        1400 : void DeclarationVisitor::Visit(Declaration* decl) {
      15        1400 :   CurrentSourcePosition::Scope scope(decl->pos);
      16        1400 :   switch (decl->kind) {
      17             : #define ENUM_ITEM(name)        \
      18             :   case AstNode::Kind::k##name: \
      19             :     return Visit(name::cast(decl));
      20        1355 :     AST_DECLARATION_NODE_KIND_LIST(ENUM_ITEM)
      21             : #undef ENUM_ITEM
      22             :     default:
      23           0 :       UNIMPLEMENTED();
      24             :   }
      25             : }
      26             : 
      27         805 : void DeclarationVisitor::Visit(CallableNode* decl, const Signature& signature,
      28             :                                base::Optional<Statement*> body) {
      29         805 :   switch (decl->kind) {
      30             : #define ENUM_ITEM(name)        \
      31             :   case AstNode::Kind::k##name: \
      32             :     return Visit(name::cast(decl), signature, body);
      33         805 :     AST_CALLABLE_NODE_KIND_LIST(ENUM_ITEM)
      34             : #undef ENUM_ITEM
      35             :     default:
      36           0 :       UNIMPLEMENTED();
      37             :   }
      38             : }
      39             : 
      40         196 : Builtin* DeclarationVisitor::CreateBuiltin(BuiltinDeclaration* decl,
      41             :                                            std::string external_name,
      42             :                                            std::string readable_name,
      43             :                                            Signature signature,
      44             :                                            base::Optional<Statement*> body) {
      45         196 :   const bool javascript = decl->javascript_linkage;
      46         196 :   const bool varargs = decl->signature->parameters.has_varargs;
      47             :   Builtin::Kind kind = !javascript ? Builtin::kStub
      48             :                                    : varargs ? Builtin::kVarArgsJavaScript
      49         196 :                                              : Builtin::kFixedArgsJavaScript;
      50             : 
      51         588 :   if (signature.types().size() == 0 ||
      52             :       !(signature.types()[0] ==
      53         588 :         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         196 :   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         196 :   if (javascript) {
      68         297 :     if (signature.types().size() < 2 ||
      69             :         !(signature.types()[1] ==
      70         297 :           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        1554 :   for (size_t i = 0; i < signature.types().size(); ++i) {
      79         679 :     if (const StructType* type =
      80         679 :             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         196 :   if (const StructType* struct_type =
      90         196 :           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         588 :   return Declarations::CreateBuiltin(
      99             :       std::move(external_name), std::move(readable_name), kind,
     100         588 :       std::move(signature), decl->transitioning, body);
     101             : }
     102             : 
     103          16 : void DeclarationVisitor::Visit(ExternalRuntimeDeclaration* decl,
     104             :                                const Signature& signature,
     105             :                                base::Optional<Statement*> body) {
     106          16 :   if (GlobalContext::verbose()) {
     107             :     std::cout << "found declaration of external runtime " << decl->name
     108           0 :               << " with signature ";
     109             :   }
     110             : 
     111          48 :   if (signature.parameter_types.types.size() == 0 ||
     112             :       !(signature.parameter_types.types[0] ==
     113          48 :         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          16 :   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          16 :   Declarations::DeclareRuntimeFunction(decl->name, signature,
     130          32 :                                        decl->transitioning);
     131          16 : }
     132             : 
     133         412 : void DeclarationVisitor::Visit(ExternalMacroDeclaration* decl,
     134             :                                const Signature& signature,
     135             :                                base::Optional<Statement*> body) {
     136         412 :   if (GlobalContext::verbose()) {
     137             :     std::cout << "found declaration of external macro " << decl->name
     138           0 :               << " with signature ";
     139             :   }
     140             : 
     141        1648 :   Declarations::DeclareMacro(decl->name, decl->external_assembler_name,
     142         824 :                              signature, decl->transitioning, body, decl->op);
     143         412 : }
     144             : 
     145         125 : void DeclarationVisitor::Visit(TorqueBuiltinDeclaration* decl,
     146             :                                const Signature& signature,
     147             :                                base::Optional<Statement*> body) {
     148         500 :   Declarations::Declare(
     149         125 :       decl->name, CreateBuiltin(decl, decl->name, decl->name, signature, body));
     150         125 : }
     151             : 
     152         235 : void DeclarationVisitor::Visit(TorqueMacroDeclaration* decl,
     153             :                                const Signature& signature,
     154             :                                base::Optional<Statement*> body) {
     155         940 :   Declarations::DeclareMacro(decl->name, base::nullopt, signature,
     156         470 :                              decl->transitioning, body, decl->op);
     157         235 : }
     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          31 : void DeclarationVisitor::Visit(ConstDeclaration* decl) {
     166          31 :   Declarations::DeclareNamespaceConstant(
     167          31 :       decl->name, Declarations::GetType(decl->type), decl->expression);
     168          31 : }
     169             : 
     170         805 : void DeclarationVisitor::Visit(StandardDeclaration* decl) {
     171        2415 :   Signature signature = MakeSignature(decl->callable->signature.get());
     172         805 :   Visit(decl->callable, signature, decl->body);
     173         805 : }
     174             : 
     175           0 : void DeclarationVisitor::Visit(GenericDeclaration* decl) {
     176          45 :   Declarations::DeclareGeneric(decl->callable->name, decl);
     177           0 : }
     178             : 
     179         139 : void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
     180         139 :   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         139 :   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         278 :   Signature signature_with_types = MakeSignature(decl->signature.get());
     192         311 :   for (Generic* generic : generic_list) {
     193             :     Signature generic_signature_with_types = MakeSpecializedSignature(
     194         516 :         SpecializationKey{generic, GetTypeVector(decl->generic_parameters)});
     195         172 :     if (signature_with_types.HasSameTypesAs(generic_signature_with_types,
     196             :                                             ParameterMode::kIgnoreImplicit)) {
     197         139 :       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         139 :   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         278 :   Specialize(SpecializationKey{matching_generic,
     228             :                                GetTypeVector(decl->generic_parameters)},
     229             :              matching_generic->declaration()->callable, decl->signature.get(),
     230         139 :              decl->body);
     231         139 : }
     232             : 
     233          89 : void DeclarationVisitor::Visit(ExternConstDeclaration* decl) {
     234          89 :   const Type* type = Declarations::GetType(decl->type);
     235          89 :   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         178 :   Declarations::DeclareExternConstant(decl->name, type, decl->literal);
     243          89 : }
     244             : 
     245         103 : void DeclarationVisitor::DeclareMethods(
     246             :     AggregateType* container_type, const std::vector<Declaration*>& methods) {
     247             :   // Declare the class' methods
     248         135 :   for (auto declaration : methods) {
     249          32 :     CurrentSourcePosition::Scope pos_scope(declaration->pos);
     250             :     StandardDeclaration* standard_declaration =
     251             :         StandardDeclaration::DynamicCast(declaration);
     252             :     DCHECK(standard_declaration);
     253             :     TorqueMacroDeclaration* method =
     254          32 :         TorqueMacroDeclaration::DynamicCast(standard_declaration->callable);
     255          64 :     Signature signature = MakeSignature(method->signature.get());
     256             :     signature.parameter_names.insert(
     257          32 :         signature.parameter_names.begin() + signature.implicit_count,
     258          64 :         MakeNode<Identifier>(kThisParameterName));
     259          32 :     Statement* body = *(standard_declaration->body);
     260             :     std::string method_name(method->name);
     261             :       signature.parameter_types.types.insert(
     262          32 :           signature.parameter_types.types.begin() + signature.implicit_count,
     263          64 :           container_type);
     264          64 :       Declarations::CreateMethod(container_type, method_name, signature, false,
     265          32 :                                  body);
     266             :   }
     267         103 : }
     268             : 
     269          14 : void DeclarationVisitor::Visit(StructDeclaration* decl) {
     270          14 :   StructType* struct_type = Declarations::DeclareStruct(decl->name);
     271          14 :   struct_declarations_.push_back(
     272          14 :       std::make_tuple(CurrentScope::Get(), decl, struct_type));
     273          14 : }
     274             : 
     275          89 : void DeclarationVisitor::Visit(ClassDeclaration* decl) {
     276             :   ClassType* new_class;
     277          89 :   if (decl->is_extern) {
     278          87 :     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         174 :     const Type* super_type = Declarations::LookupType(*decl->super);
     284          87 :     if (super_type != TypeOracle::GetTaggedType()) {
     285             :       const ClassType* super_class = ClassType::DynamicCast(super_type);
     286          86 :       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          87 :     std::string generates = decl->name->value;
     295          87 :     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         261 :     new_class = Declarations::DeclareClass(
     306         261 :         super_type, decl->name, decl->is_extern, decl->transient, generates);
     307             :   } else {
     308           2 :     if (decl->super) {
     309           0 :       ReportError("Only extern classes can inherit.");
     310             :     }
     311           2 :     if (decl->generates) {
     312           0 :       ReportError("Only extern classes can specify a generated type.");
     313             :     }
     314          10 :     new_class = Declarations::DeclareClass(TypeOracle::GetTaggedType(),
     315           4 :                                            decl->name, decl->is_extern,
     316           2 :                                            decl->transient, "FixedArray");
     317             :   }
     318          89 :   GlobalContext::RegisterClass(decl->name->value, new_class);
     319          89 :   class_declarations_.push_back(
     320          89 :       std::make_tuple(CurrentScope::Get(), decl, new_class));
     321          89 : }
     322             : 
     323          29 : void DeclarationVisitor::Visit(CppIncludeDeclaration* decl) {
     324          29 :   GlobalContext::AddCppInclude(decl->include_path);
     325          29 : }
     326             : 
     327          96 : void DeclarationVisitor::Visit(TypeDeclaration* decl) {
     328         151 :   std::string generates = decl->generates ? *decl->generates : std::string("");
     329          96 :   if (decl->generates) {
     330         205 :     if (generates.length() < 7 || generates.substr(0, 6) != "TNode<" ||
     331         123 :         generates.substr(generates.length() - 1, 1) != ">") {
     332             :       ReportError("generated type \"", generates,
     333           0 :                   "\" should be of the form \"TNode<...>\"");
     334             :     }
     335          82 :     generates = generates.substr(6, generates.length() - 7);
     336             :   }
     337             : 
     338         384 :   const AbstractType* type = Declarations::DeclareAbstractType(
     339         192 :       decl->name, decl->transient, generates, {}, decl->extends);
     340             : 
     341          96 :   if (decl->constexpr_generates) {
     342          37 :     if (decl->transient) {
     343           0 :       ReportError("cannot declare a transient type that is also constexpr");
     344             :     }
     345             :     // DeclareAbstractType expects an Identifier*. A new one is created from the
     346             :     // declaration, and the SourcePosition copied from the original name.
     347             :     Identifier* constexpr_name =
     348          74 :         MakeNode<Identifier>(CONSTEXPR_TYPE_PREFIX + decl->name->value);
     349          37 :     constexpr_name->pos = decl->name->pos;
     350             : 
     351          37 :     base::Optional<Identifier*> constexpr_extends;
     352          37 :     if (decl->extends) {
     353             :       constexpr_extends =
     354          26 :           MakeNode<Identifier>(CONSTEXPR_TYPE_PREFIX + (*decl->extends)->value);
     355          13 :       (*constexpr_extends)->pos = (*decl->extends)->pos;
     356             :     }
     357          37 :     Declarations::DeclareAbstractType(constexpr_name, false,
     358             :                                       *decl->constexpr_generates, type,
     359          37 :                                       constexpr_extends);
     360             :   }
     361          96 : }
     362             : 
     363        3197 : void DeclarationVisitor::DeclareSpecializedTypes(const SpecializationKey& key) {
     364             :   size_t i = 0;
     365             :   const std::size_t generic_parameter_count =
     366        3197 :       key.generic->declaration()->generic_parameters.size();
     367        3197 :   if (generic_parameter_count != key.specialized_types.size()) {
     368           0 :     std::stringstream stream;
     369             :     stream << "Wrong generic argument count for specialization of \""
     370           0 :            << key.generic->name() << "\", expected: " << generic_parameter_count
     371             :            << ", actual: " << key.specialized_types.size();
     372           0 :     ReportError(stream.str());
     373             :   }
     374             : 
     375        8277 :   for (auto type : key.specialized_types) {
     376             :     Identifier* generic_type_name =
     377       10160 :         key.generic->declaration()->generic_parameters[i++];
     378        5080 :     Declarations::DeclareType(generic_type_name, type, true);
     379             :   }
     380        3197 : }
     381             : 
     382        3017 : Signature DeclarationVisitor::MakeSpecializedSignature(
     383             :     const SpecializationKey& key) {
     384        3017 :   CurrentScope::Scope generic_scope(key.generic->ParentScope());
     385             :   // Create a temporary fake-namespace just to temporarily declare the
     386             :   // specialization aliases for the generic types to create a signature.
     387        9051 :   Namespace tmp_namespace("_tmp");
     388        3017 :   CurrentScope::Scope tmp_namespace_scope(&tmp_namespace);
     389        3017 :   DeclareSpecializedTypes(key);
     390        9051 :   return MakeSignature(key.generic->declaration()->callable->signature.get());
     391             : }
     392             : 
     393         180 : Callable* DeclarationVisitor::SpecializeImplicit(const SpecializationKey& key) {
     394         246 :   if (!key.generic->declaration()->body &&
     395          66 :       IntrinsicDeclaration::DynamicCast(key.generic->declaration()->callable) ==
     396             :           nullptr) {
     397           0 :     ReportError("missing specialization of ", key.generic->name(),
     398             :                 " with types <", key.specialized_types, "> declared at ",
     399           0 :                 key.generic->pos());
     400             :   }
     401         180 :   CurrentScope::Scope generic_scope(key.generic->ParentScope());
     402             :   Callable* result =
     403         360 :       Specialize(key, key.generic->declaration()->callable, base::nullopt,
     404         360 :                  key.generic->declaration()->body);
     405         180 :   CurrentScope::Scope callable_scope(result);
     406         180 :   DeclareSpecializedTypes(key);
     407         360 :   return result;
     408             : }
     409             : 
     410         319 : Callable* DeclarationVisitor::Specialize(
     411             :     const SpecializationKey& key, CallableNode* declaration,
     412             :     base::Optional<const CallableNodeSignature*> signature,
     413             :     base::Optional<Statement*> body) {
     414             :   // TODO(tebbi): The error should point to the source position where the
     415             :   // instantiation was requested.
     416         319 :   CurrentSourcePosition::Scope pos_scope(key.generic->declaration()->pos);
     417             :   size_t generic_parameter_count =
     418         319 :       key.generic->declaration()->generic_parameters.size();
     419         319 :   if (generic_parameter_count != key.specialized_types.size()) {
     420           0 :     std::stringstream stream;
     421             :     stream << "number of template parameters ("
     422           0 :            << std::to_string(key.specialized_types.size())
     423             :            << ") to intantiation of generic " << declaration->name
     424             :            << " doesnt match the generic's declaration ("
     425           0 :            << std::to_string(generic_parameter_count) << ")";
     426           0 :     ReportError(stream.str());
     427             :   }
     428         638 :   if (key.generic->GetSpecialization(key.specialized_types)) {
     429           0 :     ReportError("cannot redeclare specialization of ", key.generic->name(),
     430           0 :                 " with types <", key.specialized_types, ">");
     431             :   }
     432             : 
     433             :   Signature type_signature =
     434         638 :       signature ? MakeSignature(*signature) : MakeSpecializedSignature(key);
     435             : 
     436             :   std::string generated_name = Declarations::GetGeneratedCallableName(
     437         319 :       declaration->name, key.specialized_types);
     438         638 :   std::stringstream readable_name;
     439         319 :   readable_name << declaration->name << "<";
     440             :   bool first = true;
     441         780 :   for (const Type* t : key.specialized_types) {
     442         461 :     if (!first) readable_name << ", ";
     443         461 :     readable_name << *t;
     444             :     first = false;
     445             :   }
     446         319 :   readable_name << ">";
     447             :   Callable* callable;
     448         319 :   if (MacroDeclaration::DynamicCast(declaration) != nullptr) {
     449         796 :     callable = Declarations::CreateMacro(generated_name, readable_name.str(),
     450             :                                          base::nullopt, type_signature,
     451         398 :                                          declaration->transitioning, *body);
     452         120 :   } else if (IntrinsicDeclaration::DynamicCast(declaration) != nullptr) {
     453          66 :     callable = Declarations::CreateIntrinsic(declaration->name, type_signature);
     454             :   } else {
     455             :     BuiltinDeclaration* builtin = BuiltinDeclaration::cast(declaration);
     456         162 :     callable = CreateBuiltin(builtin, generated_name, readable_name.str(),
     457          54 :                              type_signature, *body);
     458             :   }
     459         319 :   key.generic->AddSpecialization(key.specialized_types, callable);
     460         319 :   return callable;
     461             : }
     462             : 
     463          14 : void DeclarationVisitor::FinalizeStructFieldsAndMethods(
     464             :     StructType* struct_type, StructDeclaration* struct_declaration) {
     465             :   size_t offset = 0;
     466          56 :   for (auto& field : struct_declaration->fields) {
     467          42 :     const Type* field_type = Declarations::GetType(field.name_and_type.type);
     468          42 :     struct_type->RegisterField({field.name_and_type.name->pos,
     469             :                                 struct_type,
     470             :                                 base::nullopt,
     471          42 :                                 {field.name_and_type.name->value, field_type},
     472             :                                 offset,
     473         168 :                                 false});
     474          42 :     offset += LoweredSlotCount(field_type);
     475             :   }
     476          14 :   CurrentSourcePosition::Scope position_activator(struct_declaration->pos);
     477          14 :   DeclareMethods(struct_type, struct_declaration->methods);
     478          14 : }
     479             : 
     480          89 : void DeclarationVisitor::FinalizeClassFieldsAndMethods(
     481             :     ClassType* class_type, ClassDeclaration* class_declaration) {
     482             :   const ClassType* super_class = class_type->GetSuperClass();
     483          89 :   size_t class_offset = super_class ? super_class->size() : 0;
     484             :   bool seen_indexed_field = false;
     485         337 :   for (ClassFieldExpression& field_expression : class_declaration->fields) {
     486             :     CurrentSourcePosition::Scope position_activator(
     487         248 :         field_expression.name_and_type.type->pos);
     488             :     const Type* field_type =
     489         248 :         Declarations::GetType(field_expression.name_and_type.type);
     490         248 :     if (!class_declaration->is_extern) {
     491          16 :       if (!field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
     492           0 :         ReportError("non-extern classes do not support untagged fields");
     493             :       }
     494          16 :       if (field_expression.weak) {
     495           0 :         ReportError("non-extern classes do not support weak fields");
     496             :       }
     497             :     }
     498         248 :     if (field_expression.index) {
     499           4 :       if (seen_indexed_field ||
     500           2 :           (super_class && super_class->HasIndexedField())) {
     501             :         ReportError(
     502           0 :             "only one indexable field is currently supported per class");
     503             :       }
     504             :       seen_indexed_field = true;
     505             :       const Field* index_field =
     506           2 :           &(class_type->LookupField(*field_expression.index));
     507             :       class_type->RegisterField(
     508           2 :           {field_expression.name_and_type.name->pos,
     509             :            class_type,
     510             :            index_field,
     511           2 :            {field_expression.name_and_type.name->value, field_type},
     512             :            class_offset,
     513           6 :            field_expression.weak});
     514             :     } else {
     515         246 :       if (seen_indexed_field) {
     516           0 :         ReportError("cannot declare non-indexable field \"",
     517             :                     field_expression.name_and_type.name,
     518             :                     "\" after an indexable field "
     519           0 :                     "declaration");
     520             :       }
     521             :       const Field& field = class_type->RegisterField(
     522         246 :           {field_expression.name_and_type.name->pos,
     523             :            class_type,
     524             :            base::nullopt,
     525         246 :            {field_expression.name_and_type.name->value, field_type},
     526             :            class_offset,
     527         984 :            field_expression.weak});
     528             :       size_t field_size;
     529             :       std::string size_string;
     530             :       std::string machine_type;
     531         246 :       std::tie(field_size, size_string, machine_type) =
     532         492 :           field.GetFieldSizeInformation();
     533             :       // Our allocations don't support alignments beyond kTaggedSize.
     534         492 :       size_t alignment = std::min(size_t{kTaggedSize}, field_size);
     535         246 :       if (class_offset % alignment != 0) {
     536           0 :         ReportError("field ", field_expression.name_and_type.name,
     537             :                     " at offset ", class_offset, " is not ", alignment,
     538           0 :                     "-byte aligned.");
     539             :       }
     540         246 :       class_offset += field_size;
     541             :     }
     542             :   }
     543          89 :   class_type->SetSize(class_offset);
     544             : 
     545             :   // For each field, construct AST snippits that implement a CSA accessor
     546             :   // function and define a corresponding '.field' operator. The
     547             :   // implementation iterator will turn the snippits into code.
     548         337 :   for (auto& field : class_type->fields()) {
     549         250 :     if (field.index) continue;
     550         246 :     CurrentSourcePosition::Scope position_activator(field.pos);
     551             :     IdentifierExpression* parameter =
     552         492 :         MakeNode<IdentifierExpression>(MakeNode<Identifier>(std::string{"o"}));
     553             : 
     554             :     // Load accessor
     555         246 :     std::string camel_field_name = CamelifyString(field.name_and_type.name);
     556             :     std::string load_macro_name =
     557         492 :         "Load" + class_type->name() + camel_field_name;
     558         246 :     std::string load_operator_name = "." + field.name_and_type.name;
     559         246 :     Signature load_signature;
     560         492 :     load_signature.parameter_names.push_back(MakeNode<Identifier>("o"));
     561         492 :     load_signature.parameter_types.types.push_back(class_type);
     562         246 :     load_signature.parameter_types.var_args = false;
     563         246 :     load_signature.return_type = field.name_and_type.type;
     564             :     Statement* load_body =
     565         492 :         MakeNode<ReturnStatement>(MakeNode<LoadObjectFieldExpression>(
     566             :             parameter, field.name_and_type.name));
     567         492 :     Declarations::DeclareMacro(load_macro_name, base::nullopt, load_signature,
     568         246 :                                false, load_body, load_operator_name);
     569             : 
     570             :     // Store accessor
     571         738 :     IdentifierExpression* value = MakeNode<IdentifierExpression>(
     572         246 :         std::vector<std::string>{}, MakeNode<Identifier>(std::string{"v"}));
     573             :     std::string store_macro_name =
     574         492 :         "Store" + class_type->name() + camel_field_name;
     575         492 :     std::string store_operator_name = "." + field.name_and_type.name + "=";
     576         246 :     Signature store_signature;
     577         492 :     store_signature.parameter_names.push_back(MakeNode<Identifier>("o"));
     578         492 :     store_signature.parameter_names.push_back(MakeNode<Identifier>("v"));
     579         492 :     store_signature.parameter_types.types.push_back(class_type);
     580         246 :     store_signature.parameter_types.types.push_back(field.name_and_type.type);
     581         246 :     store_signature.parameter_types.var_args = false;
     582             :     // TODO(danno): Store macros probably should return their value argument
     583         246 :     store_signature.return_type = TypeOracle::GetVoidType();
     584             :     Statement* store_body =
     585         492 :         MakeNode<ExpressionStatement>(MakeNode<StoreObjectFieldExpression>(
     586             :             parameter, field.name_and_type.name, value));
     587         492 :     Declarations::DeclareMacro(store_macro_name, base::nullopt, store_signature,
     588         246 :                                false, store_body, store_operator_name);
     589             :   }
     590             : 
     591          89 :   DeclareMethods(class_type, class_declaration->methods);
     592          89 : }
     593             : 
     594           3 : void DeclarationVisitor::FinalizeStructsAndClasses() {
     595          17 :   for (auto current_struct_info : struct_declarations_) {
     596             :     Scope* scope;
     597             :     StructDeclaration* struct_declaration;
     598             :     StructType* struct_type;
     599             :     std::tie(scope, struct_declaration, struct_type) = current_struct_info;
     600          14 :     CurrentScope::Scope scope_activator(scope);
     601          14 :     FinalizeStructFieldsAndMethods(struct_type, struct_declaration);
     602             :   }
     603             : 
     604          92 :   for (auto current_class_info : class_declarations_) {
     605             :     Scope* scope;
     606             :     ClassDeclaration* class_declaration;
     607             :     ClassType* class_type;
     608             :     std::tie(scope, class_declaration, class_type) = current_class_info;
     609          89 :     CurrentScope::Scope scope_activator(scope);
     610          89 :     CurrentSourcePosition::Scope position_activator(class_declaration->pos);
     611          89 :     FinalizeClassFieldsAndMethods(class_type, class_declaration);
     612             :   }
     613           3 : }
     614             : 
     615             : }  // namespace torque
     616             : }  // namespace internal
     617        6150 : }  // namespace v8

Generated by: LCOV version 1.10