LCOV - code coverage report
Current view: top level - src/torque - declarable.h (source / functions) Hit Total Coverage
Test: app.info Lines: 117 124 94.4 %
Date: 2019-03-21 Functions: 37 66 56.1 %

          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      331366 : 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      147616 :   explicit QualifiedName(std::string name)
      36      295232 :       : QualifiedName({}, std::move(name)) {}
      37             : 
      38             :   friend std::ostream& operator<<(std::ostream& os, const QualifiedName& name);
      39             : };
      40             : 
      41             : class Declarable {
      42             :  public:
      43       10206 :   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             :   bool IsNamespace() const { return kind() == kNamespace; }
      58       27175 :   bool IsMacro() const { return kind() == kMacro || kind() == kMethod; }
      59             :   bool IsMethod() const { return kind() == kMethod; }
      60             :   bool IsIntrinsic() const { return kind() == kIntrinsic; }
      61             :   bool IsBuiltin() const { return kind() == kBuiltin; }
      62             :   bool IsRuntimeFunction() const { return kind() == kRuntimeFunction; }
      63             :   bool IsGeneric() const { return kind() == kGeneric; }
      64             :   bool IsTypeAlias() const { return kind() == kTypeAlias; }
      65             :   bool IsExternConstant() const { return kind() == kExternConstant; }
      66             :   bool IsNamespaceConstant() const { return kind() == kNamespaceConstant; }
      67        1275 :   bool IsValue() const { return IsExternConstant() || IsNamespaceConstant(); }
      68         134 :   bool IsScope() const { return IsNamespace() || IsCallable(); }
      69             :   bool IsCallable() const {
      70       18653 :     return IsMacro() || IsBuiltin() || IsRuntimeFunction() || IsIntrinsic() ||
      71             :            IsMethod();
      72             :   }
      73           0 :   virtual const char* type_name() const { return "<<unknown>>"; }
      74             :   Scope* ParentScope() const { return parent_scope_; }
      75        7189 :   const SourcePosition& pos() const { return pos_; }
      76             : 
      77             :  protected:
      78       30618 :   explicit Declarable(Kind kind) : kind_(kind) {}
      79             : 
      80             :  private:
      81             :   const Kind kind_;
      82       10206 :   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        9414 : class Scope : public Declarable {
     108             :  public:
     109         134 :   DECLARE_DECLARABLE_BOILERPLATE(Scope, scope)
     110        4707 :   explicit Scope(Declarable::Kind kind) : Declarable(kind) {}
     111             : 
     112      238777 :   std::vector<Declarable*> LookupShallow(const QualifiedName& name) {
     113      477189 :     if (name.namespace_qualification.empty()) return declarations_[name.name];
     114             :     Scope* child = nullptr;
     115         499 :     for (Declarable* declarable :
     116         134 :          declarations_[name.namespace_qualification.front()]) {
     117         134 :       if (Scope* scope = Scope::DynamicCast(declarable)) {
     118         134 :         if (child != nullptr) {
     119             :           ReportError("ambiguous reference to scope ",
     120           0 :                       name.namespace_qualification.front());
     121             :         }
     122             :         child = scope;
     123             :       }
     124             :     }
     125         365 :     if (child == nullptr) return {};
     126             :     return child->LookupShallow(
     127             :         QualifiedName({name.namespace_qualification.begin() + 1,
     128             :                        name.namespace_qualification.end()},
     129         268 :                       name.name));
     130             :   }
     131             : 
     132      232995 :   std::vector<Declarable*> Lookup(const QualifiedName& name) {
     133             :     std::vector<Declarable*> result;
     134      232995 :     if (ParentScope()) {
     135      144604 :       result = ParentScope()->Lookup(name);
     136             :     }
     137      642043 :     for (Declarable* declarable : LookupShallow(name)) {
     138      176053 :       result.push_back(declarable);
     139             :     }
     140      232995 :     return result;
     141             :   }
     142             :   template <class T>
     143             :   T* AddDeclarable(const std::string& name, T* declarable) {
     144       14820 :     declarations_[name].push_back(declarable);
     145         120 :     return declarable;
     146             :   }
     147             : 
     148             :  private:
     149             :   std::unordered_map<std::string, std::vector<Declarable*>> declarations_;
     150             : };
     151             : 
     152        6160 : class Namespace : public Scope {
     153             :  public:
     154      110666 :   DECLARE_DECLARABLE_BOILERPLATE(Namespace, namespace)
     155        3059 :   explicit Namespace(const std::string& name)
     156        6118 :       : Scope(Declarable::kNamespace), name_(name) {}
     157        4492 :   const std::string& name() const { return name_; }
     158        2763 :   std::string ExternalName() const {
     159        5526 :     return CamelifyString(name()) + "BuiltinsFromDSLAssembler";
     160             :   }
     161             :   bool IsDefaultNamespace() const;
     162             :   bool IsTestNamespace() const;
     163        7828 :   std::ostream& source_stream() { return source_stream_; }
     164        3294 :   std::ostream& header_stream() { return header_stream_; }
     165             :   std::string source() { return source_stream_.str(); }
     166             :   std::string header() { return header_stream_.str(); }
     167             : 
     168             :  private:
     169             :   std::string name_;
     170             :   std::stringstream header_stream_;
     171             :   std::stringstream source_stream_;
     172             : };
     173             : 
     174       13008 : inline Namespace* CurrentNamespace() {
     175       13008 :   Scope* scope = CurrentScope::Get();
     176        2095 :   while (true) {
     177       15103 :     if (Namespace* n = Namespace::DynamicCast(scope)) {
     178       13008 :       return n;
     179             :     }
     180             :     scope = scope->ParentScope();
     181             :   }
     182             : }
     183             : 
     184         240 : class Value : public Declarable {
     185             :  public:
     186        2550 :   DECLARE_DECLARABLE_BOILERPLATE(Value, value)
     187             :   const Identifier* name() const { return name_; }
     188           0 :   virtual bool IsConst() const { return true; }
     189             :   VisitResult value() const { return *value_; }
     190             :   const Type* type() const { return type_; }
     191             : 
     192             :   void set_value(VisitResult value) {
     193             :     DCHECK(!value_);
     194             :     value_ = value;
     195             :   }
     196             : 
     197             :  protected:
     198             :   Value(Kind kind, const Type* type, Identifier* name)
     199         120 :       : Declarable(kind), type_(type), name_(name) {}
     200             : 
     201             :  private:
     202             :   const Type* type_;
     203             :   Identifier* name_;
     204             :   base::Optional<VisitResult> value_;
     205             : };
     206             : 
     207          62 : class NamespaceConstant : public Value {
     208             :  public:
     209         997 :   DECLARE_DECLARABLE_BOILERPLATE(NamespaceConstant, constant)
     210             : 
     211             :   Expression* body() { return body_; }
     212             :   std::string ExternalAssemblerName() const {
     213         385 :     return Namespace::cast(ParentScope())->ExternalName();
     214             :   }
     215             : 
     216             :  private:
     217             :   friend class Declarations;
     218             :   explicit NamespaceConstant(Identifier* constant_name, const Type* type,
     219             :                              Expression* body)
     220             :       : Value(Declarable::kNamespaceConstant, type, constant_name),
     221          31 :         body_(body) {}
     222             : 
     223             :   Expression* body_;
     224             : };
     225             : 
     226         178 : class ExternConstant : public Value {
     227             :  public:
     228           0 :   DECLARE_DECLARABLE_BOILERPLATE(ExternConstant, constant)
     229             : 
     230             :  private:
     231             :   friend class Declarations;
     232          89 :   explicit ExternConstant(Identifier* name, const Type* type, std::string value)
     233          89 :       : Value(Declarable::kExternConstant, type, name) {
     234          89 :     set_value(VisitResult(type, std::move(value)));
     235          89 :   }
     236             : };
     237             : 
     238        3296 : class Callable : public Scope {
     239             :  public:
     240       37306 :   DECLARE_DECLARABLE_BOILERPLATE(Callable, callable)
     241        1467 :   const std::string& ExternalName() const { return external_name_; }
     242         642 :   const std::string& ReadableName() const { return readable_name_; }
     243       19611 :   const Signature& signature() const { return signature_; }
     244             :   const NameVector& parameter_names() const {
     245         958 :     return signature_.parameter_names;
     246             :   }
     247             :   bool HasReturnValue() const {
     248        1016 :     return !signature_.return_type->IsVoidOrNever();
     249             :   }
     250        1016 :   void IncrementReturns() { ++returns_; }
     251             :   bool HasReturns() const { return returns_; }
     252             :   bool IsTransitioning() const { return transitioning_; }
     253        1244 :   base::Optional<Statement*> body() const { return body_; }
     254         466 :   bool IsExternal() const { return !body_.has_value(); }
     255        2757 :   virtual bool ShouldBeInlined() const { return false; }
     256       10371 :   virtual bool ShouldGenerateExternalCode() const { return !ShouldBeInlined(); }
     257             : 
     258             :  protected:
     259        1648 :   Callable(Declarable::Kind kind, std::string external_name,
     260             :            std::string readable_name, Signature signature, bool transitioning,
     261             :            base::Optional<Statement*> body)
     262             :       : Scope(kind),
     263             :         external_name_(std::move(external_name)),
     264             : 
     265             :         readable_name_(std::move(readable_name)),
     266             :         signature_(std::move(signature)),
     267             :         transitioning_(transitioning),
     268             :         returns_(0),
     269        3296 :         body_(body) {
     270             :     DCHECK(!body || *body);
     271        1648 :   }
     272             : 
     273             :  private:
     274             :   std::string external_name_;
     275             :   std::string readable_name_;
     276             :   Signature signature_;
     277             :   bool transitioning_;
     278             :   size_t returns_;
     279             :   base::Optional<Statement*> body_;
     280             : };
     281             : 
     282        4078 : class Macro : public Callable {
     283             :  public:
     284       12996 :   DECLARE_DECLARABLE_BOILERPLATE(Macro, macro)
     285       22509 :   bool ShouldBeInlined() const override {
     286       26113 :     for (const LabelDeclaration& label : signature().labels) {
     287        3261 :       for (const Type* type : label.types) {
     288         348 :         if (type->IsStructType()) return true;
     289             :       }
     290             :     }
     291             :     return Callable::ShouldBeInlined();
     292             :   }
     293             : 
     294             :   const std::string& external_assembler_name() const {
     295             :     return external_assembler_name_;
     296             :   }
     297             : 
     298             :  protected:
     299        1370 :   Macro(Declarable::Kind kind, std::string external_name,
     300             :         std::string readable_name, std::string external_assembler_name,
     301             :         const Signature& signature, bool transitioning,
     302             :         base::Optional<Statement*> body)
     303             :       : Callable(kind, std::move(external_name), std::move(readable_name),
     304             :                  signature, transitioning, body),
     305        5480 :         external_assembler_name_(std::move(external_assembler_name)) {
     306        1370 :     if (signature.parameter_types.var_args) {
     307           0 :       ReportError("Varargs are not supported for macros.");
     308             :     }
     309        1370 :   }
     310             : 
     311             :  private:
     312             :   friend class Declarations;
     313        1338 :   Macro(std::string external_name, std::string readable_name,
     314             :         std::string external_assembler_name, const Signature& signature,
     315             :         bool transitioning, base::Optional<Statement*> body)
     316             :       : Macro(Declarable::kMacro, std::move(external_name),
     317             :               std::move(readable_name), external_assembler_name, signature,
     318        6690 :               transitioning, body) {}
     319             : 
     320             :   std::string external_assembler_name_;
     321             : };
     322             : 
     323          32 : class Method : public Macro {
     324             :  public:
     325         958 :   DECLARE_DECLARABLE_BOILERPLATE(Method, Method)
     326         691 :   bool ShouldBeInlined() const override {
     327        1382 :     return Macro::ShouldBeInlined() ||
     328             :            signature()
     329         691 :                .parameter_types.types[signature().implicit_count]
     330        1382 :                ->IsStructType();
     331             :   }
     332             :   AggregateType* aggregate_type() const { return aggregate_type_; }
     333             : 
     334             :  private:
     335             :   friend class Declarations;
     336          32 :   Method(AggregateType* aggregate_type, std::string external_name,
     337             :          std::string readable_name, std::string external_assembler_name,
     338             :          const Signature& signature, bool transitioning, Statement* body)
     339             :       : Macro(Declarable::kMethod, std::move(external_name),
     340             :               std::move(readable_name), std::move(external_assembler_name),
     341             :               signature, transitioning, body),
     342         160 :         aggregate_type_(aggregate_type) {}
     343             :   AggregateType* aggregate_type_;
     344             : };
     345             : 
     346         196 : class Builtin : public Callable {
     347             :  public:
     348             :   enum Kind { kStub, kFixedArgsJavaScript, kVarArgsJavaScript };
     349       39590 :   DECLARE_DECLARABLE_BOILERPLATE(Builtin, builtin)
     350             :   Kind kind() const { return kind_; }
     351             :   bool IsStub() const { return kind_ == kStub; }
     352             :   bool IsVarArgsJavaScript() const { return kind_ == kVarArgsJavaScript; }
     353             :   bool IsFixedArgsJavaScript() const { return kind_ == kFixedArgsJavaScript; }
     354             : 
     355             :  private:
     356             :   friend class Declarations;
     357         196 :   Builtin(std::string external_name, std::string readable_name,
     358             :           Builtin::Kind kind, const Signature& signature, bool transitioning,
     359             :           base::Optional<Statement*> body)
     360             :       : Callable(Declarable::kBuiltin, std::move(external_name),
     361             :                  std::move(readable_name), signature, transitioning, body),
     362         784 :         kind_(kind) {}
     363             : 
     364             :   Kind kind_;
     365             : };
     366             : 
     367          16 : class RuntimeFunction : public Callable {
     368             :  public:
     369         116 :   DECLARE_DECLARABLE_BOILERPLATE(RuntimeFunction, runtime)
     370             : 
     371             :  private:
     372             :   friend class Declarations;
     373          16 :   RuntimeFunction(const std::string& name, const Signature& signature,
     374             :                   bool transitioning)
     375             :       : Callable(Declarable::kRuntimeFunction, name, name, signature,
     376          64 :                  transitioning, base::nullopt) {}
     377             : };
     378             : 
     379          66 : class Intrinsic : public Callable {
     380             :  public:
     381          93 :   DECLARE_DECLARABLE_BOILERPLATE(Intrinsic, intrinsic)
     382             : 
     383             :  private:
     384             :   friend class Declarations;
     385          66 :   Intrinsic(std::string name, const Signature& signature)
     386             :       : Callable(Declarable::kIntrinsic, name, name, signature, false,
     387         264 :                  base::nullopt) {
     388          66 :     if (signature.parameter_types.var_args) {
     389           0 :       ReportError("Varargs are not supported for intrinsics.");
     390             :     }
     391          66 :   }
     392             : };
     393             : 
     394         135 : class Generic : public Declarable {
     395             :  public:
     396       47674 :   DECLARE_DECLARABLE_BOILERPLATE(Generic, generic)
     397             : 
     398             :   GenericDeclaration* declaration() const { return declaration_; }
     399             :   const std::vector<Identifier*> generic_parameters() const {
     400             :     return declaration()->generic_parameters;
     401             :   }
     402           0 :   const std::string& name() const { return name_; }
     403             :   void AddSpecialization(const TypeVector& type_arguments,
     404             :                          Callable* specialization) {
     405             :     DCHECK_EQ(0, specializations_.count(type_arguments));
     406         319 :     specializations_[type_arguments] = specialization;
     407             :   }
     408             :   base::Optional<Callable*> GetSpecialization(
     409             :       const TypeVector& type_arguments) const {
     410             :     auto it = specializations_.find(type_arguments);
     411       29812 :     if (it != specializations_.end()) return it->second;
     412       15751 :     return base::nullopt;
     413             :   }
     414             :   base::Optional<TypeVector> InferSpecializationTypes(
     415             :       const TypeVector& explicit_specialization_types,
     416             :       const TypeVector& arguments);
     417             : 
     418             :  private:
     419             :   friend class Declarations;
     420          45 :   Generic(const std::string& name, GenericDeclaration* declaration)
     421             :       : Declarable(Declarable::kGeneric),
     422             :         name_(name),
     423          90 :         declaration_(declaration) {}
     424             :   base::Optional<const Type*> InferTypeArgument(size_t i,
     425             :                                                 const TypeVector& arguments);
     426             : 
     427             :   std::string name_;
     428             :   std::unordered_map<TypeVector, Callable*, base::hash<TypeVector>>
     429             :       specializations_;
     430             :   GenericDeclaration* declaration_;
     431             : };
     432             : 
     433        5199 : struct SpecializationKey {
     434             :   Generic* generic;
     435             :   TypeVector specialized_types;
     436             : };
     437             : 
     438       10668 : class TypeAlias : public Declarable {
     439             :  public:
     440      130685 :   DECLARE_DECLARABLE_BOILERPLATE(TypeAlias, type_alias)
     441             : 
     442             :   const Type* type() const { return type_; }
     443             :   bool IsRedeclaration() const { return redeclaration_; }
     444             :   SourcePosition GetDeclarationPosition() const {
     445           4 :     return declaration_position_;
     446             :   }
     447             : 
     448             :  private:
     449             :   friend class Declarations;
     450             :   explicit TypeAlias(
     451             :       const Type* type, bool redeclaration,
     452             :       SourcePosition declaration_position = SourcePosition::Invalid())
     453             :       : Declarable(Declarable::kTypeAlias),
     454             :         type_(type),
     455             :         redeclaration_(redeclaration),
     456        5334 :         declaration_position_(declaration_position) {}
     457             : 
     458             :   const Type* type_;
     459             :   bool redeclaration_;
     460             :   const SourcePosition declaration_position_;
     461             : };
     462             : 
     463             : std::ostream& operator<<(std::ostream& os, const Callable& m);
     464             : std::ostream& operator<<(std::ostream& os, const Builtin& b);
     465             : std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b);
     466             : std::ostream& operator<<(std::ostream& os, const Generic& g);
     467             : 
     468             : #undef DECLARE_DECLARABLE_BOILERPLATE
     469             : 
     470             : }  // namespace torque
     471             : }  // namespace internal
     472             : }  // namespace v8
     473             : 
     474             : #endif  // V8_TORQUE_DECLARABLE_H_

Generated by: LCOV version 1.10