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-04-17 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      357624 : 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      160109 :   explicit QualifiedName(std::string name)
      36      320218 :       : QualifiedName({}, std::move(name)) {}
      37             : 
      38             :   friend std::ostream& operator<<(std::ostream& os, const QualifiedName& name);
      39             : };
      40             : 
      41             : class Declarable {
      42             :  public:
      43       10704 :   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       26448 :   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        1315 :   bool IsValue() const { return IsExternConstant() || IsNamespaceConstant(); }
      68         135 :   bool IsScope() const { return IsNamespace() || IsCallable(); }
      69             :   bool IsCallable() const {
      70       18167 :     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        7588 :   const SourcePosition& pos() const { return pos_; }
      76             : 
      77             :  protected:
      78       32112 :   explicit Declarable(Kind kind) : kind_(kind) {}
      79             : 
      80             :  private:
      81             :   const Kind kind_;
      82       10704 :   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       10004 : class Scope : public Declarable {
     108             :  public:
     109         135 :   DECLARE_DECLARABLE_BOILERPLATE(Scope, scope)
     110        5002 :   explicit Scope(Declarable::Kind kind) : Declarable(kind) {}
     111             : 
     112      253274 :   std::vector<Declarable*> LookupShallow(const QualifiedName& name) {
     113      506181 :     if (name.namespace_qualification.empty()) return declarations_[name.name];
     114             :     Scope* child = nullptr;
     115         502 :     for (Declarable* declarable :
     116         135 :          declarations_[name.namespace_qualification.front()]) {
     117         135 :       if (Scope* scope = Scope::DynamicCast(declarable)) {
     118         135 :         if (child != nullptr) {
     119             :           ReportError("ambiguous reference to scope ",
     120           0 :                       name.namespace_qualification.front());
     121             :         }
     122             :         child = scope;
     123             :       }
     124             :     }
     125         367 :     if (child == nullptr) return {};
     126             :     return child->LookupShallow(
     127             :         QualifiedName({name.namespace_qualification.begin() + 1,
     128             :                        name.namespace_qualification.end()},
     129         405 :                       name.name));
     130             :   }
     131             : 
     132      247285 :   std::vector<Declarable*> Lookup(const QualifiedName& name) {
     133             :     std::vector<Declarable*> result;
     134      247285 :     if (ParentScope()) {
     135      147292 :       result = ParentScope()->Lookup(name);
     136             :     }
     137      682314 :     for (Declarable* declarable : LookupShallow(name)) {
     138      187744 :       result.push_back(declarable);
     139             :     }
     140      247285 :     return result;
     141             :   }
     142             :   template <class T>
     143             :   T* AddDeclarable(const std::string& name, T* declarable) {
     144       14608 :     declarations_[name].push_back(declarable);
     145         130 :     return declarable;
     146             :   }
     147             : 
     148             :  private:
     149             :   std::unordered_map<std::string, std::vector<Declarable*>> declarations_;
     150             : };
     151             : 
     152        6364 : class Namespace : public Scope {
     153             :  public:
     154      127663 :   DECLARE_DECLARABLE_BOILERPLATE(Namespace, namespace)
     155        3160 :   explicit Namespace(const std::string& name)
     156        6320 :       : Scope(Declarable::kNamespace), name_(name) {}
     157        5260 :   const std::string& name() const { return name_; }
     158        3290 :   std::string ExternalName() const {
     159        6580 :     return CamelifyString(name()) + "BuiltinsFromDSLAssembler";
     160             :   }
     161             :   bool IsDefaultNamespace() const;
     162             :   bool IsTestNamespace() const;
     163        8857 :   std::ostream& source_stream() { return source_stream_; }
     164        3832 :   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       14929 : inline Namespace* CurrentNamespace() {
     175       14929 :   Scope* scope = CurrentScope::Get();
     176        2225 :   while (true) {
     177       17154 :     if (Namespace* n = Namespace::DynamicCast(scope)) {
     178       14929 :       return n;
     179             :     }
     180             :     scope = scope->ParentScope();
     181             :   }
     182             : }
     183             : 
     184         260 : class Value : public Declarable {
     185             :  public:
     186        2630 :   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         130 :       : Declarable(kind), type_(type), name_(name) {}
     200             : 
     201             :  private:
     202             :   const Type* type_;
     203             :   Identifier* name_;
     204             :   base::Optional<VisitResult> value_;
     205             : };
     206             : 
     207          66 : class NamespaceConstant : public Value {
     208             :  public:
     209        1029 :   DECLARE_DECLARABLE_BOILERPLATE(NamespaceConstant, constant)
     210             : 
     211             :   Expression* body() { return body_; }
     212             :   std::string ExternalAssemblerName() const {
     213         400 :     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          33 :         body_(body) {}
     222             : 
     223             :   Expression* body_;
     224             : };
     225             : 
     226         194 : class ExternConstant : public Value {
     227             :  public:
     228           0 :   DECLARE_DECLARABLE_BOILERPLATE(ExternConstant, constant)
     229             : 
     230             :  private:
     231             :   friend class Declarations;
     232          97 :   explicit ExternConstant(Identifier* name, const Type* type, std::string value)
     233          97 :       : Value(Declarable::kExternConstant, type, name) {
     234          97 :     set_value(VisitResult(type, std::move(value)));
     235          97 :   }
     236             : };
     237             : 
     238        3684 : class Callable : public Scope {
     239             :  public:
     240       36334 :   DECLARE_DECLARABLE_BOILERPLATE(Callable, callable)
     241        1713 :   const std::string& ExternalName() const { return external_name_; }
     242         649 :   const std::string& ReadableName() const { return readable_name_; }
     243       19287 :   const Signature& signature() const { return signature_; }
     244             :   const NameVector& parameter_names() const {
     245        1120 :     return signature_.parameter_names;
     246             :   }
     247             :   bool HasReturnValue() const {
     248        1116 :     return !signature_.return_type->IsVoidOrNever();
     249             :   }
     250        1116 :   void IncrementReturns() { ++returns_; }
     251             :   bool HasReturns() const { return returns_; }
     252             :   bool IsTransitioning() const { return transitioning_; }
     253        1413 :   base::Optional<Statement*> body() const { return body_; }
     254         480 :   bool IsExternal() const { return !body_.has_value(); }
     255        2926 :   virtual bool ShouldBeInlined() const { return false; }
     256       11891 :   virtual bool ShouldGenerateExternalCode() const { return !ShouldBeInlined(); }
     257             : 
     258             :  protected:
     259        1842 :   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        3684 :         body_(body) {
     270             :     DCHECK(!body || *body);
     271        1842 :   }
     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        4605 : class Macro : public Callable {
     283             :  public:
     284       12114 :   DECLARE_DECLARABLE_BOILERPLATE(Macro, macro)
     285       23451 :   bool ShouldBeInlined() const override {
     286       27208 :     for (const LabelDeclaration& label : signature().labels) {
     287        3329 :       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        1548 :   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        6192 :         external_assembler_name_(std::move(external_assembler_name)) {
     306        1548 :     if (signature.parameter_types.var_args) {
     307           0 :       ReportError("Varargs are not supported for macros.");
     308             :     }
     309        1548 :   }
     310             : 
     311             :  private:
     312             :   friend class Declarations;
     313        1509 :   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        7545 :               transitioning, body) {}
     319             : 
     320             :   std::string external_assembler_name_;
     321             : };
     322             : 
     323          39 : class Method : public Macro {
     324             :  public:
     325        1120 :   DECLARE_DECLARABLE_BOILERPLATE(Method, Method)
     326         776 :   bool ShouldBeInlined() const override {
     327        1552 :     return Macro::ShouldBeInlined() ||
     328             :            signature()
     329         776 :                .parameter_types.types[signature().implicit_count]
     330        1552 :                ->IsStructType();
     331             :   }
     332             :   AggregateType* aggregate_type() const { return aggregate_type_; }
     333             : 
     334             :  private:
     335             :   friend class Declarations;
     336          39 :   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         195 :         aggregate_type_(aggregate_type) {}
     343             :   AggregateType* aggregate_type_;
     344             : };
     345             : 
     346         203 : class Builtin : public Callable {
     347             :  public:
     348             :   enum Kind { kStub, kFixedArgsJavaScript, kVarArgsJavaScript };
     349       41471 :   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         203 :   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         812 :         kind_(kind) {}
     363             : 
     364             :   Kind kind_;
     365             : };
     366             : 
     367          18 : class RuntimeFunction : public Callable {
     368             :  public:
     369         132 :   DECLARE_DECLARABLE_BOILERPLATE(RuntimeFunction, runtime)
     370             : 
     371             :  private:
     372             :   friend class Declarations;
     373          18 :   RuntimeFunction(const std::string& name, const Signature& signature,
     374             :                   bool transitioning)
     375             :       : Callable(Declarable::kRuntimeFunction, name, name, signature,
     376          72 :                  transitioning, base::nullopt) {}
     377             : };
     378             : 
     379          73 : class Intrinsic : public Callable {
     380             :  public:
     381         105 :   DECLARE_DECLARABLE_BOILERPLATE(Intrinsic, intrinsic)
     382             : 
     383             :  private:
     384             :   friend class Declarations;
     385          73 :   Intrinsic(std::string name, const Signature& signature)
     386             :       : Callable(Declarable::kIntrinsic, name, name, signature, false,
     387         292 :                  base::nullopt) {
     388          73 :     if (signature.parameter_types.var_args) {
     389           0 :       ReportError("Varargs are not supported for intrinsics.");
     390             :     }
     391          73 :   }
     392             : };
     393             : 
     394         138 : class Generic : public Declarable {
     395             :  public:
     396       47005 :   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         328 :     specializations_[type_arguments] = specialization;
     407             :   }
     408             :   base::Optional<Callable*> GetSpecialization(
     409             :       const TypeVector& type_arguments) const {
     410             :     auto it = specializations_.find(type_arguments);
     411       30041 :     if (it != specializations_.end()) return it->second;
     412       15309 :     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          46 :   Generic(const std::string& name, GenericDeclaration* declaration)
     421             :       : Declarable(Declarable::kGeneric),
     422             :         name_(name),
     423          92 :         declaration_(declaration) {}
     424             : 
     425             :   std::string name_;
     426             :   std::unordered_map<TypeVector, Callable*, base::hash<TypeVector>>
     427             :       specializations_;
     428             :   GenericDeclaration* declaration_;
     429             : };
     430             : 
     431        5363 : struct SpecializationKey {
     432             :   Generic* generic;
     433             :   TypeVector specialized_types;
     434             : };
     435             : 
     436       11052 : class TypeAlias : public Declarable {
     437             :  public:
     438      143125 :   DECLARE_DECLARABLE_BOILERPLATE(TypeAlias, type_alias)
     439             : 
     440             :   const Type* type() const { return type_; }
     441             :   bool IsRedeclaration() const { return redeclaration_; }
     442             :   SourcePosition GetDeclarationPosition() const {
     443           4 :     return declaration_position_;
     444             :   }
     445             : 
     446             :  private:
     447             :   friend class Declarations;
     448             :   explicit TypeAlias(
     449             :       const Type* type, bool redeclaration,
     450             :       SourcePosition declaration_position = SourcePosition::Invalid())
     451             :       : Declarable(Declarable::kTypeAlias),
     452             :         type_(type),
     453             :         redeclaration_(redeclaration),
     454        5526 :         declaration_position_(declaration_position) {}
     455             : 
     456             :   const Type* type_;
     457             :   bool redeclaration_;
     458             :   const SourcePosition declaration_position_;
     459             : };
     460             : 
     461             : std::ostream& operator<<(std::ostream& os, const Callable& m);
     462             : std::ostream& operator<<(std::ostream& os, const Builtin& b);
     463             : std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b);
     464             : std::ostream& operator<<(std::ostream& os, const Generic& g);
     465             : 
     466             : #undef DECLARE_DECLARABLE_BOILERPLATE
     467             : 
     468             : }  // namespace torque
     469             : }  // namespace internal
     470             : }  // namespace v8
     471             : 
     472             : #endif  // V8_TORQUE_DECLARABLE_H_

Generated by: LCOV version 1.10