LCOV - code coverage report
Current view: top level - src/torque - declarable.h (source / functions) Hit Total Coverage
Test: app.info Lines: 119 125 95.2 %
Date: 2019-01-20 Functions: 45 72 62.5 %

          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             : #ifndef V8_TORQUE_DECLARABLE_H_
       6             : #define V8_TORQUE_DECLARABLE_H_
       7             : 
       8             : #include <cassert>
       9             : #include <string>
      10             : #include <unordered_map>
      11             : 
      12             : #include "src/base/functional.h"
      13             : #include "src/base/logging.h"
      14             : #include "src/torque/ast.h"
      15             : #include "src/torque/types.h"
      16             : #include "src/torque/utils.h"
      17             : 
      18             : namespace v8 {
      19             : namespace internal {
      20             : namespace torque {
      21             : 
      22             : class Scope;
      23             : class Namespace;
      24             : 
      25             : DECLARE_CONTEXTUAL_VARIABLE(CurrentScope, Scope*);
      26             : 
      27      229472 : struct QualifiedName {
      28             :   std::vector<std::string> namespace_qualification;
      29             :   std::string name;
      30             : 
      31             :   QualifiedName(std::vector<std::string> namespace_qualification,
      32             :                 std::string name)
      33             :       : namespace_qualification(std::move(namespace_qualification)),
      34             :         name(std::move(name)) {}
      35      101134 :   explicit QualifiedName(std::string name)
      36      202268 :       : QualifiedName({}, std::move(name)) {}
      37             : 
      38             :   friend std::ostream& operator<<(std::ostream& os, const QualifiedName& name);
      39             : };
      40             : 
      41             : class Declarable {
      42             :  public:
      43        7169 :   virtual ~Declarable() = default;
      44             :   enum Kind {
      45             :     kNamespace,
      46             :     kMacro,
      47             :     kMethod,
      48             :     kBuiltin,
      49             :     kRuntimeFunction,
      50             :     kIntrinsic,
      51             :     kGeneric,
      52             :     kTypeAlias,
      53             :     kExternConstant,
      54             :     kNamespaceConstant
      55             :   };
      56             :   Kind kind() const { return kind_; }
      57       27976 :   bool IsNamespace() const { return kind() == kNamespace; }
      58       17811 :   bool IsMacro() const { return kind() == kMacro || kind() == kMethod; }
      59         434 :   bool IsMethod() const { return kind() == kMethod; }
      60          62 :   bool IsIntrinsic() const { return kind() == kIntrinsic; }
      61       28224 :   bool IsBuiltin() const { return kind() == kBuiltin; }
      62          82 :   bool IsRuntimeFunction() const { return kind() == kRuntimeFunction; }
      63       32333 :   bool IsGeneric() const { return kind() == kGeneric; }
      64       90579 :   bool IsTypeAlias() const { return kind() == kTypeAlias; }
      65         982 :   bool IsExternConstant() const { return kind() == kExternConstant; }
      66         787 :   bool IsNamespaceConstant() const { return kind() == kNamespaceConstant; }
      67         982 :   bool IsValue() const { return IsExternConstant() || IsNamespaceConstant(); }
      68          46 :   bool IsScope() const { return IsNamespace() || IsCallable(); }
      69       12037 :   bool IsCallable() const {
      70       12037 :     return IsMacro() || IsBuiltin() || IsRuntimeFunction() || IsIntrinsic() ||
      71       12037 :            IsMethod();
      72             :   }
      73           0 :   virtual const char* type_name() const { return "<<unknown>>"; }
      74             :   Scope* ParentScope() const { return parent_scope_; }
      75             :   const SourcePosition& pos() const { return pos_; }
      76             : 
      77             :  protected:
      78       21507 :   explicit Declarable(Kind kind) : kind_(kind) {}
      79             : 
      80             :  private:
      81             :   const Kind kind_;
      82             :   Scope* const parent_scope_ = CurrentScope::Get();
      83             :   SourcePosition pos_ = CurrentSourcePosition::Get();
      84             : };
      85             : 
      86             : #define DECLARE_DECLARABLE_BOILERPLATE(x, y)                  \
      87             :   static x* cast(Declarable* declarable) {                    \
      88             :     DCHECK(declarable->Is##x());                              \
      89             :     return static_cast<x*>(declarable);                       \
      90             :   }                                                           \
      91             :   static const x* cast(const Declarable* declarable) {        \
      92             :     DCHECK(declarable->Is##x());                              \
      93             :     return static_cast<const x*>(declarable);                 \
      94             :   }                                                           \
      95             :   const char* type_name() const override { return #y; }       \
      96             :   static x* DynamicCast(Declarable* declarable) {             \
      97             :     if (!declarable) return nullptr;                          \
      98             :     if (!declarable->Is##x()) return nullptr;                 \
      99             :     return static_cast<x*>(declarable);                       \
     100             :   }                                                           \
     101             :   static const x* DynamicCast(const Declarable* declarable) { \
     102             :     if (!declarable) return nullptr;                          \
     103             :     if (!declarable->Is##x()) return nullptr;                 \
     104             :     return static_cast<const x*>(declarable);                 \
     105             :   }
     106             : 
     107        6332 : class Scope : public Declarable {
     108             :  public:
     109          92 :   DECLARE_DECLARABLE_BOILERPLATE(Scope, scope);
     110        6332 :   explicit Scope(Declarable::Kind kind) : Declarable(kind) {}
     111             : 
     112      168478 :   std::vector<Declarable*> LookupShallow(const QualifiedName& name) {
     113      336864 :     if (name.namespace_qualification.empty()) return declarations_[name.name];
     114             :     Scope* child = nullptr;
     115         322 :     for (Declarable* declarable :
     116          46 :          declarations_[name.namespace_qualification.front()]) {
     117          46 :       if (Scope* scope = Scope::DynamicCast(declarable)) {
     118          46 :         if (child != nullptr) {
     119             :           ReportError("ambiguous reference to scope ",
     120           0 :                       name.namespace_qualification.front());
     121             :         }
     122             :         child = scope;
     123             :       }
     124             :     }
     125         138 :     if (child == nullptr) return {};
     126             :     return child->LookupShallow(
     127             :         QualifiedName({name.namespace_qualification.begin() + 1,
     128             :                        name.namespace_qualification.end()},
     129         138 :                       name.name));
     130             :   }
     131             : 
     132      164330 :   std::vector<Declarable*> Lookup(const QualifiedName& name) {
     133             :     std::vector<Declarable*> result;
     134      164330 :     if (ParentScope()) {
     135      105924 :       result = ParentScope()->Lookup(name);
     136             :     }
     137      614134 :     for (Declarable* declarable : LookupShallow(name)) {
     138      121144 :       result.push_back(declarable);
     139             :     }
     140      164330 :     return result;
     141             :   }
     142             :   template <class T>
     143         828 :   T* AddDeclarable(const std::string& name, T* declarable) {
     144        9570 :     declarations_[name].push_back(declarable);
     145         938 :     return declarable;
     146             :   }
     147             : 
     148             :  private:
     149             :   std::unordered_map<std::string, std::vector<Declarable*>> declarations_;
     150             : };
     151             : 
     152        4348 : class Namespace : public Scope {
     153             :  public:
     154       55860 :   DECLARE_DECLARABLE_BOILERPLATE(Namespace, namespace);
     155        2169 :   explicit Namespace(const std::string& name)
     156        2169 :       : Scope(Declarable::kNamespace), name_(name) {}
     157             :   const std::string& name() const { return name_; }
     158        1323 :   std::string ExternalName() const {
     159        2646 :     return CamelifyString(name()) + "BuiltinsFromDSLAssembler";
     160             :   }
     161             :   std::ostream& source_stream() { return source_stream_; }
     162             :   std::ostream& header_stream() { return header_stream_; }
     163             :   std::string source() { return source_stream_.str(); }
     164             :   std::string header() { return header_stream_.str(); }
     165             : 
     166             :  private:
     167             :   std::string name_;
     168             :   std::stringstream header_stream_;
     169             :   std::stringstream source_stream_;
     170             : };
     171             : 
     172        6850 : inline Namespace* CurrentNamespace() {
     173        6850 :   Scope* scope = CurrentScope::Get();
     174             :   while (true) {
     175        8190 :     if (Namespace* n = Namespace::DynamicCast(scope)) {
     176        6850 :       return n;
     177             :     }
     178        1340 :     scope = scope->ParentScope();
     179        1340 :   }
     180             : }
     181             : 
     182         220 : class Value : public Declarable {
     183             :  public:
     184        1964 :   DECLARE_DECLARABLE_BOILERPLATE(Value, value);
     185             :   const std::string& name() const { return name_; }
     186           0 :   virtual bool IsConst() const { return true; }
     187         470 :   VisitResult value() const { return *value_; }
     188             :   const Type* type() const { return type_; }
     189             : 
     190             :   void set_value(VisitResult value) {
     191             :     DCHECK(!value_);
     192             :     value_ = value;
     193             :   }
     194             : 
     195             :  protected:
     196         110 :   Value(Kind kind, const Type* type, const std::string& name)
     197         110 :       : Declarable(kind), type_(type), name_(name) {}
     198             : 
     199             :  private:
     200             :   const Type* type_;
     201             :   std::string name_;
     202             :   base::Optional<VisitResult> value_;
     203             : };
     204             : 
     205         120 : class NamespaceConstant : public Value {
     206             :  public:
     207        1574 :   DECLARE_DECLARABLE_BOILERPLATE(NamespaceConstant, constant);
     208             : 
     209             :   const std::string& constant_name() const { return constant_name_; }
     210             :   Expression* body() { return body_; }
     211             :   std::string ExternalAssemblerName() const {
     212         317 :     return Namespace::cast(ParentScope())->ExternalName();
     213             :   }
     214             : 
     215             :  private:
     216             :   friend class Declarations;
     217             :   explicit NamespaceConstant(std::string constant_name, const Type* type,
     218             :                              Expression* body)
     219             :       : Value(Declarable::kNamespaceConstant, type, constant_name),
     220             :         constant_name_(std::move(constant_name)),
     221          80 :         body_(body) {}
     222             : 
     223             :   std::string constant_name_;
     224             :   Expression* body_;
     225             : };
     226             : 
     227          70 : class ExternConstant : public Value {
     228             :  public:
     229           0 :   DECLARE_DECLARABLE_BOILERPLATE(ExternConstant, constant);
     230             : 
     231             :  private:
     232             :   friend class Declarations;
     233          70 :   explicit ExternConstant(std::string name, const Type* type, std::string value)
     234          70 :       : Value(Declarable::kExternConstant, type, std::move(name)) {
     235          70 :     set_value(VisitResult(type, std::move(value)));
     236          70 :   }
     237             : };
     238             : 
     239        1994 : class Callable : public Scope {
     240             :  public:
     241       12037 :   DECLARE_DECLARABLE_BOILERPLATE(Callable, callable);
     242             :   const std::string& ExternalName() const { return external_name_; }
     243             :   const std::string& ReadableName() const { return readable_name_; }
     244             :   const Signature& signature() const { return signature_; }
     245             :   const NameVector& parameter_names() const {
     246             :     return signature_.parameter_names;
     247             :   }
     248             :   bool HasReturnValue() const {
     249         574 :     return !signature_.return_type->IsVoidOrNever();
     250             :   }
     251         574 :   void IncrementReturns() { ++returns_; }
     252             :   bool HasReturns() const { return returns_; }
     253             :   bool IsTransitioning() const { return transitioning_; }
     254             :   base::Optional<Statement*> body() const { return body_; }
     255        1939 :   bool IsExternal() const { return !body_.has_value(); }
     256         415 :   virtual bool ShouldBeInlined() const { return false; }
     257           8 :   bool IsConstructor() const { return readable_name_ == kConstructMethodName; }
     258             : 
     259             :  protected:
     260         997 :   Callable(Declarable::Kind kind, std::string external_name,
     261             :            std::string readable_name, Signature signature, bool transitioning,
     262             :            base::Optional<Statement*> body)
     263             :       : Scope(kind),
     264             :         external_name_(std::move(external_name)),
     265             : 
     266             :         readable_name_(std::move(readable_name)),
     267             :         signature_(std::move(signature)),
     268             :         transitioning_(transitioning),
     269             :         returns_(0),
     270        1994 :         body_(body) {
     271             :     DCHECK(!body || *body);
     272         997 :   }
     273             : 
     274             :  private:
     275             :   std::string external_name_;
     276             :   std::string readable_name_;
     277             :   Signature signature_;
     278             :   bool transitioning_;
     279             :   size_t returns_;
     280             :   base::Optional<Statement*> body_;
     281             : };
     282             : 
     283        2389 : class Macro : public Callable {
     284             :  public:
     285        9256 :   DECLARE_DECLARABLE_BOILERPLATE(Macro, macro);
     286       11588 :   bool ShouldBeInlined() const override {
     287       25255 :     for (const LabelDeclaration& label : signature().labels) {
     288        3715 :       for (const Type* type : label.types) {
     289          98 :         if (type->IsStructType()) return true;
     290             :       }
     291             :     }
     292             :     return Callable::ShouldBeInlined();
     293             :   }
     294             : 
     295             :   const std::string& external_assembler_name() const {
     296             :     return external_assembler_name_;
     297             :   }
     298             : 
     299             :  protected:
     300         803 :   Macro(Declarable::Kind kind, std::string external_name,
     301             :         std::string readable_name, std::string external_assembler_name,
     302             :         const Signature& signature, bool transitioning,
     303             :         base::Optional<Statement*> body)
     304             :       : Callable(kind, std::move(external_name), std::move(readable_name),
     305             :                  signature, transitioning, body),
     306        3212 :         external_assembler_name_(std::move(external_assembler_name)) {
     307         803 :     if (signature.parameter_types.var_args) {
     308           0 :       ReportError("Varargs are not supported for macros.");
     309             :     }
     310         803 :   }
     311             : 
     312             :  private:
     313             :   friend class Declarations;
     314         783 :   Macro(std::string external_name, std::string readable_name,
     315             :         std::string external_assembler_name, const Signature& signature,
     316             :         bool transitioning, base::Optional<Statement*> body)
     317             :       : Macro(Declarable::kMacro, std::move(external_name),
     318             :               std::move(readable_name), external_assembler_name, signature,
     319        3915 :               transitioning, body) {}
     320             : 
     321             :   std::string external_assembler_name_;
     322             : };
     323             : 
     324          20 : class Method : public Macro {
     325             :  public:
     326         868 :   DECLARE_DECLARABLE_BOILERPLATE(Method, Method);
     327         136 :   bool ShouldBeInlined() const override {
     328         272 :     return Macro::ShouldBeInlined() ||
     329         272 :            signature().parameter_types.types[0]->IsStructType();
     330             :   }
     331             :   AggregateType* aggregate_type() const { return aggregate_type_; }
     332             : 
     333             :  private:
     334             :   friend class Declarations;
     335          20 :   Method(AggregateType* aggregate_type, std::string external_name,
     336             :          std::string readable_name, std::string external_assembler_name,
     337             :          const Signature& signature, bool transitioning, Statement* body)
     338             :       : Macro(Declarable::kMethod, std::move(external_name),
     339             :               std::move(readable_name), std::move(external_assembler_name),
     340             :               signature, transitioning, body),
     341         100 :         aggregate_type_(aggregate_type) {}
     342             :   AggregateType* aggregate_type_;
     343             : };
     344             : 
     345         134 : class Builtin : public Callable {
     346             :  public:
     347             :   enum Kind { kStub, kFixedArgsJavaScript, kVarArgsJavaScript };
     348       56448 :   DECLARE_DECLARABLE_BOILERPLATE(Builtin, builtin);
     349             :   Kind kind() const { return kind_; }
     350             :   bool IsStub() const { return kind_ == kStub; }
     351             :   bool IsVarArgsJavaScript() const { return kind_ == kVarArgsJavaScript; }
     352             :   bool IsFixedArgsJavaScript() const { return kind_ == kFixedArgsJavaScript; }
     353             : 
     354             :  private:
     355             :   friend class Declarations;
     356         134 :   Builtin(std::string external_name, std::string readable_name,
     357             :           Builtin::Kind kind, const Signature& signature, bool transitioning,
     358             :           base::Optional<Statement*> body)
     359             :       : Callable(Declarable::kBuiltin, std::move(external_name),
     360             :                  std::move(readable_name), signature, transitioning, body),
     361         536 :         kind_(kind) {}
     362             : 
     363             :   Kind kind_;
     364             : };
     365             : 
     366          11 : class RuntimeFunction : public Callable {
     367             :  public:
     368         164 :   DECLARE_DECLARABLE_BOILERPLATE(RuntimeFunction, runtime);
     369             : 
     370             :  private:
     371             :   friend class Declarations;
     372          11 :   RuntimeFunction(const std::string& name, const Signature& signature,
     373             :                   bool transitioning)
     374             :       : Callable(Declarable::kRuntimeFunction, name, name, signature,
     375          33 :                  transitioning, base::nullopt) {}
     376             : };
     377             : 
     378          49 : class Intrinsic : public Callable {
     379             :  public:
     380         124 :   DECLARE_DECLARABLE_BOILERPLATE(Intrinsic, intrinsic);
     381             : 
     382             :  private:
     383             :   friend class Declarations;
     384          49 :   Intrinsic(std::string name, const Signature& signature)
     385             :       : Callable(Declarable::kIntrinsic, name, name, signature, false,
     386         147 :                  base::nullopt) {
     387          49 :     if (signature.parameter_types.var_args) {
     388           0 :       ReportError("Varargs are not supported for intrinsics.");
     389             :     }
     390          49 :   }
     391             : };
     392             : 
     393         144 : class Generic : public Declarable {
     394             :  public:
     395       64666 :   DECLARE_DECLARABLE_BOILERPLATE(Generic, generic);
     396             : 
     397             :   GenericDeclaration* declaration() const { return declaration_; }
     398             :   const std::vector<std::string> generic_parameters() const {
     399             :     return declaration()->generic_parameters;
     400             :   }
     401             :   const std::string& name() const { return name_; }
     402             :   void AddSpecialization(const TypeVector& type_arguments,
     403             :                          Callable* specialization) {
     404             :     DCHECK_EQ(0, specializations_.count(type_arguments));
     405         302 :     specializations_[type_arguments] = specialization;
     406             :   }
     407       16019 :   base::Optional<Callable*> GetSpecialization(
     408             :       const TypeVector& type_arguments) const {
     409             :     auto it = specializations_.find(type_arguments);
     410       16019 :     if (it != specializations_.end()) return it->second;
     411             :     return base::nullopt;
     412             :   }
     413             :   base::Optional<TypeVector> InferSpecializationTypes(
     414             :       const TypeVector& explicit_specialization_types,
     415             :       const TypeVector& arguments);
     416             : 
     417             :  private:
     418             :   friend class Declarations;
     419          48 :   Generic(const std::string& name, GenericDeclaration* declaration)
     420             :       : Declarable(Declarable::kGeneric),
     421             :         name_(name),
     422          96 :         declaration_(declaration) {}
     423             :   base::Optional<const Type*> InferTypeArgument(size_t i,
     424             :                                                 const TypeVector& arguments);
     425             : 
     426             :   std::string name_;
     427             :   std::unordered_map<TypeVector, Callable*, base::hash<TypeVector>>
     428             :       specializations_;
     429             :   GenericDeclaration* declaration_;
     430             : };
     431             : 
     432             : struct SpecializationKey {
     433             :   Generic* generic;
     434             :   TypeVector specialized_types;
     435             : };
     436             : 
     437        7690 : class TypeAlias : public Declarable {
     438             :  public:
     439      181158 :   DECLARE_DECLARABLE_BOILERPLATE(TypeAlias, type_alias);
     440             : 
     441             :   const Type* type() const { return type_; }
     442             :   bool IsRedeclaration() const { return redeclaration_; }
     443             : 
     444             :  private:
     445             :   friend class Declarations;
     446             :   explicit TypeAlias(const Type* type, bool redeclaration)
     447             :       : Declarable(Declarable::kTypeAlias),
     448             :         type_(type),
     449        3845 :         redeclaration_(redeclaration) {}
     450             : 
     451             :   const Type* type_;
     452             :   bool redeclaration_;
     453             : };
     454             : 
     455             : std::ostream& operator<<(std::ostream& os, const Callable& m);
     456             : std::ostream& operator<<(std::ostream& os, const Builtin& b);
     457             : std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b);
     458             : std::ostream& operator<<(std::ostream& os, const Generic& g);
     459             : 
     460             : #undef DECLARE_DECLARABLE_BOILERPLATE
     461             : 
     462             : }  // namespace torque
     463             : }  // namespace internal
     464             : }  // namespace v8
     465             : 
     466             : #endif  // V8_TORQUE_DECLARABLE_H_

Generated by: LCOV version 1.10