LCOV - code coverage report
Current view: top level - src/torque - implementation-visitor.h (source / functions) Hit Total Coverage
Test: app.info Lines: 72 75 96.0 %
Date: 2019-01-20 Functions: 22 22 100.0 %

          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_IMPLEMENTATION_VISITOR_H_
       6             : #define V8_TORQUE_IMPLEMENTATION_VISITOR_H_
       7             : 
       8             : #include <string>
       9             : 
      10             : #include "src/base/macros.h"
      11             : #include "src/torque/ast.h"
      12             : #include "src/torque/cfg.h"
      13             : #include "src/torque/file-visitor.h"
      14             : #include "src/torque/global-context.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             : // LocationReference is the representation of an l-value, so a value that might
      23             : // allow for assignment. For uniformity, this class can also represent
      24             : // unassignable temporaries. Assignable values fall in two categories:
      25             : //   - stack ranges that represent mutable variables, including structs.
      26             : //   - field or element access expressions that generate operator calls.
      27       12636 : class LocationReference {
      28             :  public:
      29             :   // An assignable stack range.
      30             :   static LocationReference VariableAccess(VisitResult variable) {
      31             :     DCHECK(variable.IsOnStack());
      32        1647 :     LocationReference result;
      33             :     result.variable_ = std::move(variable);
      34             :     return result;
      35             :   }
      36             :   // An unassignable value. {description} is only used for error messages.
      37             :   static LocationReference Temporary(VisitResult temporary,
      38             :                                      std::string description) {
      39        4112 :     LocationReference result;
      40             :     result.temporary_ = std::move(temporary);
      41             :     result.temporary_description_ = std::move(description);
      42             :     return result;
      43             :   }
      44         195 :   static LocationReference ArrayAccess(VisitResult base, VisitResult offset) {
      45         195 :     LocationReference result;
      46         390 :     result.eval_function_ = std::string{"[]"};
      47         390 :     result.assign_function_ = std::string{"[]="};
      48         585 :     result.call_arguments_ = {base, offset};
      49         195 :     return result;
      50             :   }
      51         244 :   static LocationReference FieldAccess(VisitResult object,
      52             :                                        std::string fieldname) {
      53         244 :     LocationReference result;
      54         488 :     result.eval_function_ = "." + fieldname;
      55         732 :     result.assign_function_ = "." + fieldname + "=";
      56         732 :     result.call_arguments_ = {object};
      57         244 :     return result;
      58             :   }
      59             : 
      60             :   bool IsConst() const { return temporary_.has_value(); }
      61             : 
      62        2451 :   bool IsVariableAccess() const { return variable_.has_value(); }
      63             :   const VisitResult& variable() const {
      64             :     DCHECK(IsVariableAccess());
      65             :     return *variable_;
      66             :   }
      67        5973 :   bool IsTemporary() const { return temporary_.has_value(); }
      68             :   const VisitResult& temporary() const {
      69             :     DCHECK(IsTemporary());
      70             :     return *temporary_;
      71             :   }
      72             : 
      73             :   const VisitResult& GetVisitResult() const {
      74          49 :     if (IsVariableAccess()) return variable();
      75             :     DCHECK(IsTemporary());
      76          15 :     return temporary();
      77             :   }
      78             : 
      79             :   // For error reporting.
      80             :   const std::string& temporary_description() const {
      81             :     DCHECK(IsTemporary());
      82             :     return *temporary_description_;
      83             :   }
      84             : 
      85             :   bool IsCallAccess() const {
      86         510 :     bool is_call_access = eval_function_.has_value();
      87             :     DCHECK_EQ(is_call_access, assign_function_.has_value());
      88             :     return is_call_access;
      89             :   }
      90             :   const VisitResultVector& call_arguments() const {
      91             :     DCHECK(IsCallAccess());
      92             :     return call_arguments_;
      93             :   }
      94             :   const std::string& eval_function() const {
      95             :     DCHECK(IsCallAccess());
      96             :     return *eval_function_;
      97             :   }
      98             :   const std::string& assign_function() const {
      99             :     DCHECK(IsCallAccess());
     100             :     return *assign_function_;
     101             :   }
     102             : 
     103             :  private:
     104             :   base::Optional<VisitResult> variable_;
     105             :   base::Optional<VisitResult> temporary_;
     106             :   base::Optional<std::string> temporary_description_;
     107             :   base::Optional<std::string> eval_function_;
     108             :   base::Optional<std::string> assign_function_;
     109             :   VisitResultVector call_arguments_;
     110             : 
     111       12396 :   LocationReference() = default;
     112             : };
     113             : 
     114             : template <class T>
     115             : class Binding;
     116             : 
     117             : template <class T>
     118        1224 : class BindingsManager {
     119             :  public:
     120       14035 :   base::Optional<Binding<T>*> TryLookup(const std::string& name) {
     121       14035 :     return current_bindings_[name];
     122             :   }
     123             : 
     124             :  private:
     125             :   friend class Binding<T>;
     126             :   std::unordered_map<std::string, base::Optional<Binding<T>*>>
     127             :       current_bindings_;
     128             : };
     129             : 
     130             : template <class T>
     131             : class Binding : public T {
     132             :  public:
     133             :   template <class... Args>
     134        4560 :   Binding(BindingsManager<T>* manager, const std::string& name, Args&&... args)
     135             :       : T(std::forward<Args>(args)...),
     136             :         manager_(manager),
     137             :         name_(name),
     138        9120 :         previous_binding_(this) {
     139        9120 :     std::swap(previous_binding_, manager_->current_bindings_[name]);
     140        4560 :   }
     141        9120 :   ~Binding() { manager_->current_bindings_[name_] = previous_binding_; }
     142             : 
     143             :   const std::string& name() const { return name_; }
     144           0 :   SourcePosition declaration_position() const { return declaration_position_; }
     145             : 
     146             :  private:
     147             :   BindingsManager<T>* manager_;
     148             :   const std::string name_;
     149             :   base::Optional<Binding*> previous_binding_;
     150             :   SourcePosition declaration_position_ = CurrentSourcePosition::Get();
     151             :   DISALLOW_COPY_AND_ASSIGN(Binding);
     152             : };
     153             : 
     154             : template <class T>
     155        2010 : class BlockBindings {
     156             :  public:
     157        2462 :   explicit BlockBindings(BindingsManager<T>* manager) : manager_(manager) {}
     158        2536 :   void Add(std::string name, T value) {
     159        8537 :     for (const auto& binding : bindings_) {
     160        3465 :       if (binding->name() == name) {
     161           0 :         ReportError(
     162             :             "redeclaration of name \"", name,
     163             :             "\" in the same block is illegal, previous declaration at: ",
     164           0 :             binding->declaration_position());
     165             :       }
     166             :     }
     167        5072 :     bindings_.push_back(base::make_unique<Binding<T>>(manager_, std::move(name),
     168             :                                                       std::move(value)));
     169        2536 :   }
     170             : 
     171             :   std::vector<Binding<T>*> bindings() const {
     172             :     std::vector<Binding<T>*> result;
     173             :     result.reserve(bindings_.size());
     174             :     for (auto& b : bindings_) {
     175             :       result.push_back(b.get());
     176             :     }
     177             :     return result;
     178             :   }
     179             : 
     180             :  private:
     181             :   BindingsManager<T>* manager_;
     182             :   std::vector<std::unique_ptr<Binding<T>>> bindings_;
     183             : };
     184             : 
     185        2435 : struct LocalValue {
     186             :   bool is_const;
     187             :   VisitResult value;
     188             : };
     189             : 
     190        2150 : struct LocalLabel {
     191             :   Block* block;
     192             :   std::vector<const Type*> parameter_types;
     193             : 
     194             :   explicit LocalLabel(Block* block,
     195             :                       std::vector<const Type*> parameter_types = {})
     196        2150 :       : block(block), parameter_types(std::move(parameter_types)) {}
     197             : };
     198             : 
     199       32869 : struct Arguments {
     200             :   VisitResultVector parameters;
     201             :   std::vector<Binding<LocalLabel>*> labels;
     202             : };
     203             : 
     204             : bool IsCompatibleSignature(const Signature& sig, const TypeVector& types,
     205             :                            const std::vector<Binding<LocalLabel>*>& labels);
     206             : 
     207             : class ImplementationVisitor : public FileVisitor {
     208             :  public:
     209             :   void GenerateBuiltinDefinitions(std::string& file_name);
     210             :   void GenerateClassDefinitions(std::string& file_name);
     211             : 
     212             :   VisitResult Visit(Expression* expr);
     213             :   const Type* Visit(Statement* stmt);
     214             : 
     215             :   VisitResult Visit(StructExpression* decl);
     216             : 
     217             :   LocationReference GetLocationReference(Expression* location);
     218             :   LocationReference GetLocationReference(IdentifierExpression* expr);
     219             :   LocationReference GetLocationReference(FieldAccessExpression* expr);
     220             :   LocationReference GetLocationReference(ElementAccessExpression* expr);
     221             : 
     222             :   VisitResult GenerateFetchFromLocation(const LocationReference& reference);
     223             : 
     224             :   VisitResult GetBuiltinCode(Builtin* builtin);
     225             : 
     226             :   VisitResult Visit(IdentifierExpression* expr);
     227         259 :   VisitResult Visit(FieldAccessExpression* expr) {
     228             :     StackScope scope(this);
     229         777 :     return scope.Yield(GenerateFetchFromLocation(GetLocationReference(expr)));
     230             :   }
     231         134 :   VisitResult Visit(ElementAccessExpression* expr) {
     232             :     StackScope scope(this);
     233         402 :     return scope.Yield(GenerateFetchFromLocation(GetLocationReference(expr)));
     234             :   }
     235             : 
     236             :   void VisitAllDeclarables();
     237             :   void Visit(Declarable* delarable);
     238             :   void Visit(TypeAlias* decl);
     239             :   VisitResult InlineMacro(Macro* macro,
     240             :                           base::Optional<LocationReference> this_reference,
     241             :                           const std::vector<VisitResult>& arguments,
     242             :                           const std::vector<Block*> label_blocks);
     243             :   void VisitMacroCommon(Macro* macro);
     244             :   void Visit(Macro* macro);
     245             :   void Visit(Method* macro);
     246             :   void Visit(Builtin* builtin);
     247             :   void Visit(NamespaceConstant* decl);
     248             : 
     249             :   VisitResult Visit(CallExpression* expr, bool is_tail = false);
     250             :   VisitResult Visit(CallMethodExpression* expr);
     251             :   VisitResult Visit(IntrinsicCallExpression* intrinsic);
     252             :   VisitResult Visit(LoadObjectFieldExpression* intrinsic);
     253             :   VisitResult Visit(StoreObjectFieldExpression* intrinsic);
     254             :   const Type* Visit(TailCallStatement* stmt);
     255             : 
     256             :   VisitResult Visit(ConditionalExpression* expr);
     257             : 
     258             :   VisitResult Visit(LogicalOrExpression* expr);
     259             :   VisitResult Visit(LogicalAndExpression* expr);
     260             : 
     261             :   VisitResult Visit(IncrementDecrementExpression* expr);
     262             :   VisitResult Visit(AssignmentExpression* expr);
     263             :   VisitResult Visit(StringLiteralExpression* expr);
     264             :   VisitResult Visit(NumberLiteralExpression* expr);
     265             :   VisitResult Visit(AssumeTypeImpossibleExpression* expr);
     266             :   VisitResult Visit(TryLabelExpression* expr);
     267             :   VisitResult Visit(StatementExpression* expr);
     268             :   VisitResult Visit(NewExpression* expr);
     269             : 
     270             :   const Type* Visit(ReturnStatement* stmt);
     271             :   const Type* Visit(GotoStatement* stmt);
     272             :   const Type* Visit(IfStatement* stmt);
     273             :   const Type* Visit(WhileStatement* stmt);
     274             :   const Type* Visit(BreakStatement* stmt);
     275             :   const Type* Visit(ContinueStatement* stmt);
     276             :   const Type* Visit(ForLoopStatement* stmt);
     277             :   const Type* Visit(VarDeclarationStatement* stmt);
     278             :   const Type* Visit(VarDeclarationStatement* stmt,
     279             :                     BlockBindings<LocalValue>* block_bindings);
     280             :   const Type* Visit(ForOfLoopStatement* stmt);
     281             :   const Type* Visit(BlockStatement* block);
     282             :   const Type* Visit(ExpressionStatement* stmt);
     283             :   const Type* Visit(DebugStatement* stmt);
     284             :   const Type* Visit(AssertStatement* stmt);
     285             : 
     286             :   void BeginNamespaceFile(Namespace* nspace);
     287             :   void EndNamespaceFile(Namespace* nspace);
     288             : 
     289             :   void GenerateImplementation(const std::string& dir, Namespace* nspace);
     290             : 
     291             :   struct ConstructorInfo {
     292             :     int super_calls;
     293             :     bool accessed_this;
     294             :   };
     295             : 
     296             :   DECLARE_CONTEXTUAL_VARIABLE(ValueBindingsManager,
     297             :                               BindingsManager<LocalValue>);
     298             :   DECLARE_CONTEXTUAL_VARIABLE(LabelBindingsManager,
     299             :                               BindingsManager<LocalLabel>);
     300             :   DECLARE_CONTEXTUAL_VARIABLE(CurrentCallable, Callable*);
     301             :   DECLARE_CONTEXTUAL_VARIABLE(CurrentReturnValue, base::Optional<VisitResult>);
     302             :   DECLARE_CONTEXTUAL_VARIABLE(CurrentConstructorInfo,
     303             :                               base::Optional<ConstructorInfo>);
     304             : 
     305             :   // A BindingsManagersScope has to be active for local bindings to be created.
     306             :   // Shadowing an existing BindingsManagersScope by creating a new one hides all
     307             :   // existing bindings while the additional BindingsManagersScope is active.
     308        1224 :   struct BindingsManagersScope {
     309             :     ValueBindingsManager::Scope value_bindings_manager;
     310             :     LabelBindingsManager::Scope label_bindings_manager;
     311             :   };
     312             : 
     313             :  private:
     314             :   base::Optional<Block*> GetCatchBlock();
     315             :   void GenerateCatchBlock(base::Optional<Block*> catch_block);
     316             : 
     317             :   // {StackScope} records the stack height at creation time and reconstructs it
     318             :   // when being destructed by emitting a {DeleteRangeInstruction}, except for
     319             :   // the slots protected by {StackScope::Yield}. Calling {Yield(v)} deletes all
     320             :   // slots above the initial stack height except for the slots of {v}, which are
     321             :   // moved to form the only slots above the initial height and marks them to
     322             :   // survive destruction of the {StackScope}. A typical pattern is the
     323             :   // following:
     324             :   //
     325             :   // VisitResult result;
     326             :   // {
     327             :   //   StackScope stack_scope(this);
     328             :   //   // ... create temporary slots ...
     329             :   //   result = stack_scope.Yield(surviving_slots);
     330             :   // }
     331             :   class StackScope {
     332             :    public:
     333       24479 :     explicit StackScope(ImplementationVisitor* visitor) : visitor_(visitor) {
     334       24479 :       base_ = visitor_->assembler().CurrentStack().AboveTop();
     335             :     }
     336       38496 :     VisitResult Yield(VisitResult result) {
     337             :       DCHECK(!closed_);
     338       20628 :       closed_ = true;
     339       20628 :       if (!result.IsOnStack()) {
     340        5520 :         if (!visitor_->assembler().CurrentBlockIsComplete()) {
     341        2646 :           visitor_->assembler().DropTo(base_);
     342             :         }
     343        2760 :         return result;
     344             :       }
     345             :       DCHECK_LE(base_, result.stack_range().begin());
     346             :       DCHECK_LE(result.stack_range().end(),
     347             :                 visitor_->assembler().CurrentStack().AboveTop());
     348       17868 :       visitor_->assembler().DropTo(result.stack_range().end());
     349       17868 :       visitor_->assembler().DeleteRange(
     350       17868 :           StackRange{base_, result.stack_range().begin()});
     351       35736 :       base_ = visitor_->assembler().CurrentStack().AboveTop();
     352             :       return VisitResult(result.type(), visitor_->assembler().TopRange(
     353             :                                             result.stack_range().Size()));
     354             :     }
     355             : 
     356        3851 :     void Close() {
     357             :       DCHECK(!closed_);
     358        3851 :       closed_ = true;
     359        7702 :       if (!visitor_->assembler().CurrentBlockIsComplete()) {
     360        1947 :         visitor_->assembler().DropTo(base_);
     361             :       }
     362        3851 :     }
     363             : 
     364             :     ~StackScope() {
     365       24479 :       if (closed_) {
     366             :         DCHECK_IMPLIES(
     367             :             !visitor_->assembler().CurrentBlockIsComplete(),
     368             :             base_ == visitor_->assembler().CurrentStack().AboveTop());
     369             :       } else {
     370        3851 :         Close();
     371             :       }
     372             :     }
     373             : 
     374             :    private:
     375             :     ImplementationVisitor* visitor_;
     376             :     BottomOffset base_;
     377             :     bool closed_ = false;
     378             :   };
     379             : 
     380          78 :   class BreakContinueActivator {
     381             :    public:
     382          78 :     BreakContinueActivator(Block* break_block, Block* continue_block)
     383             :         : break_binding_{&LabelBindingsManager::Get(), "_break",
     384             :                          LocalLabel{break_block}},
     385             :           continue_binding_{&LabelBindingsManager::Get(), "_continue",
     386         624 :                             LocalLabel{continue_block}} {}
     387             : 
     388             :    private:
     389             :     Binding<LocalLabel> break_binding_;
     390             :     Binding<LocalLabel> continue_binding_;
     391             :   };
     392             : 
     393             :   base::Optional<Binding<LocalValue>*> TryLookupLocalValue(
     394             :       const std::string& name);
     395             :   base::Optional<Binding<LocalLabel>*> TryLookupLabel(const std::string& name);
     396             :   Binding<LocalLabel>* LookupLabel(const std::string& name);
     397             :   Block* LookupSimpleLabel(const std::string& name);
     398             :   template <class Container>
     399             :   Callable* LookupCall(const QualifiedName& name,
     400             :                        const Container& declaration_container,
     401             :                        const Arguments& arguments,
     402             :                        const TypeVector& specialization_types);
     403             : 
     404             :   const Type* GetCommonType(const Type* left, const Type* right);
     405             : 
     406             :   VisitResult GenerateCopy(const VisitResult& to_copy);
     407             : 
     408             :   void GenerateAssignToLocation(const LocationReference& reference,
     409             :                                 const VisitResult& assignment_value);
     410             : 
     411             :   void AddCallParameter(Callable* callable, VisitResult parameter,
     412             :                         const Type* parameter_type,
     413             :                         std::vector<VisitResult>* converted_arguments,
     414             :                         StackRange* argument_range,
     415             :                         std::vector<std::string>* constexpr_arguments);
     416             : 
     417             :   VisitResult GenerateCall(Callable* callable,
     418             :                            base::Optional<LocationReference> this_parameter,
     419             :                            Arguments parameters,
     420             :                            const TypeVector& specialization_types = {},
     421             :                            bool tail_call = false);
     422             :   VisitResult GenerateCall(const QualifiedName& callable_name,
     423             :                            Arguments parameters,
     424             :                            const TypeVector& specialization_types = {},
     425             :                            bool tail_call = false);
     426        1766 :   VisitResult GenerateCall(std::string callable_name, Arguments parameters,
     427             :                            const TypeVector& specialization_types = {},
     428             :                            bool tail_call = false) {
     429             :     return GenerateCall(QualifiedName(std::move(callable_name)),
     430        5298 :                         std::move(parameters), specialization_types, tail_call);
     431             :   }
     432             :   VisitResult GeneratePointerCall(Expression* callee,
     433             :                                   const Arguments& parameters, bool tail_call);
     434             : 
     435             :   void GenerateBranch(const VisitResult& condition, Block* true_block,
     436             :                       Block* false_block);
     437             : 
     438             :   void GenerateExpressionBranch(Expression* expression, Block* true_block,
     439             :                                 Block* false_block);
     440             : 
     441             :   void GenerateMacroFunctionDeclaration(std::ostream& o,
     442             :                                         const std::string& macro_prefix,
     443             :                                         Macro* macro);
     444             :   void GenerateFunctionDeclaration(std::ostream& o,
     445             :                                    const std::string& macro_prefix,
     446             :                                    const std::string& name,
     447             :                                    const Signature& signature,
     448             :                                    const NameVector& parameter_names);
     449             : 
     450             :   VisitResult GenerateImplicitConvert(const Type* destination_type,
     451             :                                       VisitResult source);
     452             : 
     453             :   StackRange GenerateLabelGoto(LocalLabel* label,
     454             :                                base::Optional<StackRange> arguments = {});
     455             : 
     456             :   std::vector<Binding<LocalLabel>*> LabelsFromIdentifiers(
     457             :       const std::vector<std::string>& names);
     458             : 
     459             :   StackRange LowerParameter(const Type* type, const std::string& parameter_name,
     460             :                             Stack<std::string>* lowered_parameters);
     461             : 
     462             :   std::string ExternalLabelName(const std::string& label_name);
     463             :   std::string ExternalLabelParameterName(const std::string& label_name,
     464             :                                          size_t i);
     465             :   std::string ExternalParameterName(const std::string& name);
     466             : 
     467        4286 :   std::ostream& source_out() { return CurrentNamespace()->source_stream(); }
     468             : 
     469        1626 :   std::ostream& header_out() { return CurrentNamespace()->header_stream(); }
     470             : 
     471             :   CfgAssembler& assembler() { return *assembler_; }
     472             : 
     473             :   void SetReturnValue(VisitResult return_value) {
     474             :     base::Optional<VisitResult>& current_return_value =
     475             :         CurrentReturnValue::Get();
     476             :     DCHECK_IMPLIES(current_return_value, *current_return_value == return_value);
     477             :     current_return_value = std::move(return_value);
     478             :   }
     479             : 
     480             :   VisitResult GetAndClearReturnValue() {
     481         452 :     VisitResult return_value = *CurrentReturnValue::Get();
     482             :     CurrentReturnValue::Get() = base::nullopt;
     483             :     return return_value;
     484             :   }
     485             : 
     486             :   base::Optional<CfgAssembler> assembler_;
     487             : };
     488             : 
     489             : }  // namespace torque
     490             : }  // namespace internal
     491             : }  // namespace v8
     492             : 
     493             : #endif  // V8_TORQUE_IMPLEMENTATION_VISITOR_H_

Generated by: LCOV version 1.10