LCOV - code coverage report
Current view: top level - src/torque - implementation-visitor.h (source / functions) Hit Total Coverage
Test: app.info Lines: 96 97 99.0 %
Date: 2019-03-21 Functions: 31 31 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       20168 : class LocationReference {
      28             :  public:
      29             :   // An assignable stack range.
      30             :   static LocationReference VariableAccess(VisitResult variable) {
      31             :     DCHECK(variable.IsOnStack());
      32             :     LocationReference result;
      33             :     result.variable_ = std::move(variable);
      34             :     return result;
      35             :   }
      36             :   // An unassignable value. {description} is only used for error messages.
      37        5891 :   static LocationReference Temporary(VisitResult temporary,
      38             :                                      std::string description) {
      39             :     LocationReference result;
      40             :     result.temporary_ = std::move(temporary);
      41             :     result.temporary_description_ = std::move(description);
      42        5891 :     return result;
      43             :   }
      44         148 :   static LocationReference ArrayAccess(VisitResult base, VisitResult offset) {
      45             :     LocationReference result;
      46         296 :     result.eval_function_ = std::string{"[]"};
      47         296 :     result.assign_function_ = std::string{"[]="};
      48         296 :     result.call_arguments_ = {base, offset};
      49         148 :     return result;
      50             :   }
      51         439 :   static LocationReference FieldAccess(VisitResult object,
      52             :                                        std::string fieldname) {
      53             :     LocationReference result;
      54         878 :     result.eval_function_ = "." + fieldname;
      55        1317 :     result.assign_function_ = "." + fieldname + "=";
      56         878 :     result.call_arguments_ = {object};
      57             :     result.index_field_ = base::nullopt;
      58         439 :     return result;
      59             :   }
      60         126 :   static LocationReference IndexedFieldIndexedAccess(
      61             :       const LocationReference& indexed_field, VisitResult index) {
      62             :     LocationReference result;
      63             :     DCHECK(indexed_field.IsIndexedFieldAccess());
      64             :     std::string fieldname = *indexed_field.index_field_;
      65         378 :     result.eval_function_ = "." + fieldname + "[]";
      66         378 :     result.assign_function_ = "." + fieldname + "[]=";
      67             :     result.call_arguments_ = indexed_field.call_arguments_;
      68         126 :     result.call_arguments_.push_back(index);
      69             :     result.index_field_ = fieldname;
      70         126 :     return result;
      71             :   }
      72         126 :   static LocationReference IndexedFieldAccess(VisitResult object,
      73             :                                               std::string fieldname) {
      74             :     LocationReference result;
      75         252 :     result.call_arguments_ = {object};
      76             :     result.index_field_ = fieldname;
      77         126 :     return result;
      78             :   }
      79             : 
      80             :   bool IsConst() const { return temporary_.has_value(); }
      81             : 
      82             :   bool IsVariableAccess() const { return variable_.has_value(); }
      83             :   const VisitResult& variable() const {
      84             :     DCHECK(IsVariableAccess());
      85             :     return *variable_;
      86             :   }
      87             :   bool IsTemporary() const { return temporary_.has_value(); }
      88             :   const VisitResult& temporary() const {
      89             :     DCHECK(IsTemporary());
      90             :     return *temporary_;
      91             :   }
      92             : 
      93             :   const VisitResult& GetVisitResult() const {
      94         642 :     if (IsVariableAccess()) return variable();
      95             :     DCHECK(IsTemporary());
      96             :     return temporary();
      97             :   }
      98             : 
      99             :   // For error reporting.
     100             :   const std::string& temporary_description() const {
     101             :     DCHECK(IsTemporary());
     102             :     return *temporary_description_;
     103             :   }
     104             : 
     105             :   bool IsArrayField() const { return index_field_.has_value(); }
     106             :   bool IsIndexedFieldAccess() const {
     107         873 :     return IsArrayField() && !IsCallAccess();
     108             :   }
     109             :   bool IsIndexedFieldIndexedAccess() const {
     110             :     return IsArrayField() && IsCallAccess();
     111             :   }
     112             :   bool IsCallAccess() const {
     113             :     bool is_call_access = eval_function_.has_value();
     114             :     DCHECK_EQ(is_call_access, assign_function_.has_value());
     115             :     return is_call_access;
     116             :   }
     117             :   const VisitResultVector& call_arguments() const {
     118             :     DCHECK(IsCallAccess());
     119             :     return call_arguments_;
     120             :   }
     121             :   const std::string& eval_function() const {
     122             :     DCHECK(IsCallAccess());
     123             :     return *eval_function_;
     124             :   }
     125             :   const std::string& assign_function() const {
     126             :     DCHECK(IsCallAccess());
     127             :     return *assign_function_;
     128             :   }
     129             : 
     130             :  private:
     131             :   base::Optional<VisitResult> variable_;
     132             :   base::Optional<VisitResult> temporary_;
     133             :   base::Optional<std::string> temporary_description_;
     134             :   base::Optional<std::string> eval_function_;
     135             :   base::Optional<std::string> assign_function_;
     136             :   VisitResultVector call_arguments_;
     137             :   base::Optional<std::string> index_field_;
     138             : 
     139             :   LocationReference() = default;
     140             : };
     141             : 
     142          24 : struct InitializerResults {
     143             :   std::vector<VisitResult> results;
     144             : };
     145             : 
     146             : template <class T>
     147             : class Binding;
     148             : 
     149             : template <class T>
     150        2550 : class BindingsManager {
     151             :  public:
     152             :   base::Optional<Binding<T>*> TryLookup(const std::string& name) {
     153       18415 :     return current_bindings_[name];
     154             :   }
     155             : 
     156             :  private:
     157             :   friend class Binding<T>;
     158             :   std::unordered_map<std::string, base::Optional<Binding<T>*>>
     159             :       current_bindings_;
     160             : };
     161             : 
     162             : template <class T>
     163             : class Binding : public T {
     164             :  public:
     165             :   template <class... Args>
     166        7505 :   Binding(BindingsManager<T>* manager, const std::string& name, Args&&... args)
     167             :       : T(std::forward<Args>(args)...),
     168             :         manager_(manager),
     169             :         name_(name),
     170       15010 :         previous_binding_(this) {
     171       15010 :     std::swap(previous_binding_, manager_->current_bindings_[name]);
     172        7505 :   }
     173             :   template <class... Args>
     174             :   Binding(BindingsManager<T>* manager, const Identifier* name, Args&&... args)
     175        3811 :       : Binding(manager, name->value, std::forward<Args>(args)...) {
     176        3811 :     declaration_position_ = name->pos;
     177             :   }
     178       15010 :   ~Binding() { manager_->current_bindings_[name_] = previous_binding_; }
     179             : 
     180        4874 :   const std::string& name() const { return name_; }
     181           1 :   SourcePosition declaration_position() const { return declaration_position_; }
     182             : 
     183             :  private:
     184             :   BindingsManager<T>* manager_;
     185             :   const std::string name_;
     186             :   base::Optional<Binding*> previous_binding_;
     187             :   SourcePosition declaration_position_ = CurrentSourcePosition::Get();
     188             :   DISALLOW_COPY_AND_ASSIGN(Binding);
     189             : };
     190             : 
     191             : template <class T>
     192        3389 : class BlockBindings {
     193             :  public:
     194        4454 :   explicit BlockBindings(BindingsManager<T>* manager) : manager_(manager) {}
     195         386 :   void Add(std::string name, T value) {
     196         386 :     ReportErrorIfAlreadyBound(name);
     197         772 :     bindings_.push_back(base::make_unique<Binding<T>>(manager_, std::move(name),
     198             :                                                       std::move(value)));
     199         386 :   }
     200             : 
     201        3811 :   void Add(const Identifier* name, T value) {
     202        3811 :     ReportErrorIfAlreadyBound(name->value);
     203        7622 :     bindings_.push_back(
     204             :         base::make_unique<Binding<T>>(manager_, name, std::move(value)));
     205        3811 :   }
     206             : 
     207             :   std::vector<Binding<T>*> bindings() const {
     208             :     std::vector<Binding<T>*> result;
     209             :     result.reserve(bindings_.size());
     210             :     for (auto& b : bindings_) {
     211             :       result.push_back(b.get());
     212             :     }
     213             :     return result;
     214             :   }
     215             : 
     216             :  private:
     217        4197 :   void ReportErrorIfAlreadyBound(const std::string& name) {
     218        9071 :     for (const auto& binding : bindings_) {
     219        4874 :       if (binding->name() == name) {
     220           0 :         ReportError(
     221             :             "redeclaration of name \"", name,
     222             :             "\" in the same block is illegal, previous declaration at: ",
     223             :             binding->declaration_position());
     224             :       }
     225             :     }
     226        4197 :   }
     227             : 
     228             :   BindingsManager<T>* manager_;
     229             :   std::vector<std::unique_ptr<Binding<T>>> bindings_;
     230             : };
     231             : 
     232       12363 : struct LocalValue {
     233             :   bool is_const;
     234             :   VisitResult value;
     235             : };
     236             : 
     237       10428 : struct LocalLabel {
     238             :   Block* block;
     239             :   std::vector<const Type*> parameter_types;
     240             : 
     241             :   explicit LocalLabel(Block* block,
     242             :                       std::vector<const Type*> parameter_types = {})
     243        3476 :       : block(block), parameter_types(std::move(parameter_types)) {}
     244             : };
     245             : 
     246       44108 : struct Arguments {
     247             :   VisitResultVector parameters;
     248             :   std::vector<Binding<LocalLabel>*> labels;
     249             : };
     250             : 
     251             : // Determine if a callable should be considered as an overload.
     252             : bool IsCompatibleSignature(const Signature& sig, const TypeVector& types,
     253             :                            size_t label_count);
     254             : 
     255           9 : class ImplementationVisitor : public FileVisitor {
     256             :  public:
     257             :   void GenerateBuiltinDefinitions(std::string& file_name);
     258             :   void GenerateClassDefinitions(std::string& file_name);
     259             : 
     260             :   VisitResult Visit(Expression* expr);
     261             :   const Type* Visit(Statement* stmt);
     262             : 
     263             :   InitializerResults VisitInitializerResults(
     264             :       const std::vector<Expression*>& expressions);
     265             : 
     266             :   size_t InitializeAggregateHelper(
     267             :       const AggregateType* aggregate_type, VisitResult allocate_result,
     268             :       const InitializerResults& initializer_results);
     269             : 
     270             :   void InitializeAggregate(const AggregateType* aggregate_type,
     271             :                            VisitResult allocate_result,
     272             :                            const InitializerResults& initializer_results);
     273             : 
     274             :   VisitResult TemporaryUninitializedStruct(const StructType* struct_type,
     275             :                                            const std::string& reason);
     276             :   VisitResult Visit(StructExpression* decl);
     277             : 
     278             :   LocationReference GetLocationReference(Expression* location);
     279             :   LocationReference GetLocationReference(IdentifierExpression* expr);
     280             :   LocationReference GetLocationReference(FieldAccessExpression* expr);
     281             :   LocationReference GetLocationReference(ElementAccessExpression* expr);
     282             : 
     283             :   VisitResult GenerateFetchFromLocation(const LocationReference& reference);
     284             : 
     285             :   VisitResult GetBuiltinCode(Builtin* builtin);
     286             : 
     287             :   VisitResult Visit(IdentifierExpression* expr);
     288         633 :   VisitResult Visit(FieldAccessExpression* expr) {
     289             :     StackScope scope(this);
     290        1899 :     return scope.Yield(GenerateFetchFromLocation(GetLocationReference(expr)));
     291             :   }
     292         211 :   VisitResult Visit(ElementAccessExpression* expr) {
     293             :     StackScope scope(this);
     294         633 :     return scope.Yield(GenerateFetchFromLocation(GetLocationReference(expr)));
     295             :   }
     296             : 
     297             :   void VisitAllDeclarables();
     298             :   void Visit(Declarable* delarable);
     299             :   void Visit(TypeAlias* decl);
     300             :   VisitResult InlineMacro(Macro* macro,
     301             :                           base::Optional<LocationReference> this_reference,
     302             :                           const std::vector<VisitResult>& arguments,
     303             :                           const std::vector<Block*> label_blocks);
     304             :   void VisitMacroCommon(Macro* macro);
     305             :   void Visit(Macro* macro);
     306             :   void Visit(Method* macro);
     307             :   void Visit(Builtin* builtin);
     308             :   void Visit(NamespaceConstant* decl);
     309             : 
     310             :   VisitResult Visit(CallExpression* expr, bool is_tail = false);
     311             :   VisitResult Visit(CallMethodExpression* expr);
     312             :   VisitResult Visit(IntrinsicCallExpression* intrinsic);
     313             :   VisitResult Visit(LoadObjectFieldExpression* expr);
     314             :   VisitResult Visit(StoreObjectFieldExpression* expr);
     315             :   const Type* Visit(TailCallStatement* stmt);
     316             : 
     317             :   VisitResult Visit(ConditionalExpression* expr);
     318             : 
     319             :   VisitResult Visit(LogicalOrExpression* expr);
     320             :   VisitResult Visit(LogicalAndExpression* expr);
     321             : 
     322             :   VisitResult Visit(IncrementDecrementExpression* expr);
     323             :   VisitResult Visit(AssignmentExpression* expr);
     324             :   VisitResult Visit(StringLiteralExpression* expr);
     325             :   VisitResult Visit(NumberLiteralExpression* expr);
     326             :   VisitResult Visit(AssumeTypeImpossibleExpression* expr);
     327             :   VisitResult Visit(TryLabelExpression* expr);
     328             :   VisitResult Visit(StatementExpression* expr);
     329             :   VisitResult Visit(NewExpression* expr);
     330             : 
     331             :   const Type* Visit(ReturnStatement* stmt);
     332             :   const Type* Visit(GotoStatement* stmt);
     333             :   const Type* Visit(IfStatement* stmt);
     334             :   const Type* Visit(WhileStatement* stmt);
     335             :   const Type* Visit(BreakStatement* stmt);
     336             :   const Type* Visit(ContinueStatement* stmt);
     337             :   const Type* Visit(ForLoopStatement* stmt);
     338             :   const Type* Visit(VarDeclarationStatement* stmt);
     339             :   const Type* Visit(VarDeclarationStatement* stmt,
     340             :                     BlockBindings<LocalValue>* block_bindings);
     341             :   const Type* Visit(ForOfLoopStatement* stmt);
     342             :   const Type* Visit(BlockStatement* block);
     343             :   const Type* Visit(ExpressionStatement* stmt);
     344             :   const Type* Visit(DebugStatement* stmt);
     345             :   const Type* Visit(AssertStatement* stmt);
     346             : 
     347             :   void BeginNamespaceFile(Namespace* nspace);
     348             :   void EndNamespaceFile(Namespace* nspace);
     349             : 
     350             :   void GenerateImplementation(const std::string& dir, Namespace* nspace);
     351             : 
     352             :   DECLARE_CONTEXTUAL_VARIABLE(ValueBindingsManager,
     353             :                               BindingsManager<LocalValue>);
     354             :   DECLARE_CONTEXTUAL_VARIABLE(LabelBindingsManager,
     355             :                               BindingsManager<LocalLabel>);
     356             :   DECLARE_CONTEXTUAL_VARIABLE(CurrentCallable, Callable*);
     357             :   DECLARE_CONTEXTUAL_VARIABLE(CurrentReturnValue, base::Optional<VisitResult>);
     358             : 
     359             :   // A BindingsManagersScope has to be active for local bindings to be created.
     360             :   // Shadowing an existing BindingsManagersScope by creating a new one hides all
     361             :   // existing bindings while the additional BindingsManagersScope is active.
     362        5100 :   struct BindingsManagersScope {
     363             :     ValueBindingsManager::Scope value_bindings_manager;
     364             :     LabelBindingsManager::Scope label_bindings_manager;
     365             :   };
     366             : 
     367             :  private:
     368             :   base::Optional<Block*> GetCatchBlock();
     369             :   void GenerateCatchBlock(base::Optional<Block*> catch_block);
     370             : 
     371             :   // {StackScope} records the stack height at creation time and reconstructs it
     372             :   // when being destructed by emitting a {DeleteRangeInstruction}, except for
     373             :   // the slots protected by {StackScope::Yield}. Calling {Yield(v)} deletes all
     374             :   // slots above the initial stack height except for the slots of {v}, which are
     375             :   // moved to form the only slots above the initial height and marks them to
     376             :   // survive destruction of the {StackScope}. A typical pattern is the
     377             :   // following:
     378             :   //
     379             :   // VisitResult result;
     380             :   // {
     381             :   //   StackScope stack_scope(this);
     382             :   //   // ... create temporary slots ...
     383             :   //   result = stack_scope.Yield(surviving_slots);
     384             :   // }
     385             :   class StackScope {
     386             :    public:
     387       33292 :     explicit StackScope(ImplementationVisitor* visitor) : visitor_(visitor) {
     388       33292 :       base_ = visitor_->assembler().CurrentStack().AboveTop();
     389             :     }
     390       27541 :     VisitResult Yield(VisitResult result) {
     391             :       DCHECK(!closed_);
     392       27541 :       closed_ = true;
     393       27541 :       if (!result.IsOnStack()) {
     394        6740 :         if (!visitor_->assembler().CurrentBlockIsComplete()) {
     395        6358 :           visitor_->assembler().DropTo(base_);
     396             :         }
     397        3370 :         return result;
     398             :       }
     399             :       DCHECK_LE(base_, result.stack_range().begin());
     400             :       DCHECK_LE(result.stack_range().end(),
     401             :                 visitor_->assembler().CurrentStack().AboveTop());
     402       48342 :       visitor_->assembler().DropTo(result.stack_range().end());
     403       48342 :       visitor_->assembler().DeleteRange(
     404       24171 :           StackRange{base_, result.stack_range().begin()});
     405       48342 :       base_ = visitor_->assembler().CurrentStack().AboveTop();
     406             :       return VisitResult(result.type(), visitor_->assembler().TopRange(
     407             :                                             result.stack_range().Size()));
     408             :     }
     409             : 
     410        5751 :     void Close() {
     411             :       DCHECK(!closed_);
     412        5751 :       closed_ = true;
     413       11502 :       if (!visitor_->assembler().CurrentBlockIsComplete()) {
     414        5498 :         visitor_->assembler().DropTo(base_);
     415             :       }
     416        5751 :     }
     417             : 
     418       33292 :     ~StackScope() {
     419       33292 :       if (closed_) {
     420             :         DCHECK_IMPLIES(
     421             :             !visitor_->assembler().CurrentBlockIsComplete(),
     422             :             base_ == visitor_->assembler().CurrentStack().AboveTop());
     423             :       } else {
     424        5751 :         Close();
     425             :       }
     426             :     }
     427             : 
     428             :    private:
     429             :     ImplementationVisitor* visitor_;
     430             :     BottomOffset base_;
     431             :     bool closed_ = false;
     432             :   };
     433             : 
     434         103 :   class BreakContinueActivator {
     435             :    public:
     436         103 :     BreakContinueActivator(Block* break_block, Block* continue_block)
     437             :         : break_binding_{&LabelBindingsManager::Get(), "_break",
     438             :                          LocalLabel{break_block}},
     439             :           continue_binding_{&LabelBindingsManager::Get(), "_continue",
     440         824 :                             LocalLabel{continue_block}} {}
     441             : 
     442             :    private:
     443             :     Binding<LocalLabel> break_binding_;
     444             :     Binding<LocalLabel> continue_binding_;
     445             :   };
     446             : 
     447             :   base::Optional<Binding<LocalValue>*> TryLookupLocalValue(
     448             :       const std::string& name);
     449             :   base::Optional<Binding<LocalLabel>*> TryLookupLabel(const std::string& name);
     450             :   Binding<LocalLabel>* LookupLabel(const std::string& name);
     451             :   Block* LookupSimpleLabel(const std::string& name);
     452             :   template <class Container>
     453             :   Callable* LookupCallable(const QualifiedName& name,
     454             :                            const Container& declaration_container,
     455             :                            const TypeVector& types,
     456             :                            const std::vector<Binding<LocalLabel>*>& labels,
     457             :                            const TypeVector& specialization_types);
     458             : 
     459             :   template <class Container>
     460             :   Callable* LookupCallable(const QualifiedName& name,
     461             :                            const Container& declaration_container,
     462             :                            const Arguments& arguments,
     463             :                            const TypeVector& specialization_types);
     464             : 
     465             :   Method* LookupMethod(const std::string& name, LocationReference target,
     466             :                        const Arguments& arguments,
     467             :                        const TypeVector& specialization_types);
     468             : 
     469             :   const Type* GetCommonType(const Type* left, const Type* right);
     470             : 
     471             :   VisitResult GenerateCopy(const VisitResult& to_copy);
     472             : 
     473             :   void GenerateAssignToLocation(const LocationReference& reference,
     474             :                                 const VisitResult& assignment_value);
     475             : 
     476             :   void AddCallParameter(Callable* callable, VisitResult parameter,
     477             :                         const Type* parameter_type,
     478             :                         std::vector<VisitResult>* converted_arguments,
     479             :                         StackRange* argument_range,
     480             :                         std::vector<std::string>* constexpr_arguments);
     481             : 
     482             :   VisitResult GenerateCall(Callable* callable,
     483             :                            base::Optional<LocationReference> this_parameter,
     484             :                            Arguments parameters,
     485             :                            const TypeVector& specialization_types = {},
     486             :                            bool tail_call = false);
     487             :   VisitResult GenerateCall(const QualifiedName& callable_name,
     488             :                            Arguments parameters,
     489             :                            const TypeVector& specialization_types = {},
     490             :                            bool tail_call = false);
     491        2405 :   VisitResult GenerateCall(std::string callable_name, Arguments parameters,
     492             :                            const TypeVector& specialization_types = {},
     493             :                            bool tail_call = false) {
     494             :     return GenerateCall(QualifiedName(std::move(callable_name)),
     495        7215 :                         std::move(parameters), specialization_types, tail_call);
     496             :   }
     497             :   VisitResult GeneratePointerCall(Expression* callee,
     498             :                                   const Arguments& parameters, bool tail_call);
     499             : 
     500             :   void GenerateBranch(const VisitResult& condition, Block* true_block,
     501             :                       Block* false_block);
     502             : 
     503             :   void GenerateExpressionBranch(Expression* expression, Block* true_block,
     504             :                                 Block* false_block);
     505             : 
     506             :   void GenerateMacroFunctionDeclaration(std::ostream& o,
     507             :                                         const std::string& macro_prefix,
     508             :                                         Macro* macro);
     509             :   void GenerateFunctionDeclaration(std::ostream& o,
     510             :                                    const std::string& macro_prefix,
     511             :                                    const std::string& name,
     512             :                                    const Signature& signature,
     513             :                                    const NameVector& parameter_names);
     514             : 
     515             :   VisitResult GenerateImplicitConvert(const Type* destination_type,
     516             :                                       VisitResult source);
     517             : 
     518             :   StackRange GenerateLabelGoto(LocalLabel* label,
     519             :                                base::Optional<StackRange> arguments = {});
     520             : 
     521             :   std::vector<Binding<LocalLabel>*> LabelsFromIdentifiers(
     522             :       const std::vector<std::string>& names);
     523             : 
     524             :   StackRange LowerParameter(const Type* type, const std::string& parameter_name,
     525             :                             Stack<std::string>* lowered_parameters);
     526             : 
     527             :   void LowerLabelParameter(const Type* type, const std::string& parameter_name,
     528             :                            std::vector<std::string>* lowered_parameters);
     529             : 
     530             :   std::string ExternalLabelName(const std::string& label_name);
     531             :   std::string ExternalLabelParameterName(const std::string& label_name,
     532             :                                          size_t i);
     533             :   std::string ExternalParameterName(const std::string& name);
     534             : 
     535        7893 :   std::ostream& source_out() {
     536        7893 :     Callable* callable = CurrentCallable::Get();
     537        7893 :     if (!callable || callable->ShouldGenerateExternalCode()) {
     538       15492 :       return CurrentNamespace()->source_stream();
     539             :     } else {
     540         147 :       return null_stream_;
     541             :     }
     542             :   }
     543        3293 :   std::ostream& header_out() {
     544        3293 :     Callable* callable = CurrentCallable::Get();
     545        3293 :     if (!callable || callable->ShouldGenerateExternalCode()) {
     546        6424 :       return CurrentNamespace()->header_stream();
     547             :     } else {
     548          81 :       return null_stream_;
     549             :     }
     550             :   }
     551             :   CfgAssembler& assembler() { return *assembler_; }
     552             : 
     553             :   void SetReturnValue(VisitResult return_value) {
     554             :     base::Optional<VisitResult>& current_return_value =
     555             :         CurrentReturnValue::Get();
     556             :     DCHECK_IMPLIES(current_return_value, *current_return_value == return_value);
     557             :     current_return_value = std::move(return_value);
     558             :   }
     559             : 
     560        1065 :   VisitResult GetAndClearReturnValue() {
     561             :     VisitResult return_value = *CurrentReturnValue::Get();
     562             :     CurrentReturnValue::Get() = base::nullopt;
     563        1065 :     return return_value;
     564             :   }
     565             : 
     566             :   base::Optional<CfgAssembler> assembler_;
     567             :   NullOStream null_stream_;
     568             : };
     569             : 
     570             : }  // namespace torque
     571             : }  // namespace internal
     572             : }  // namespace v8
     573             : 
     574             : #endif  // V8_TORQUE_IMPLEMENTATION_VISITOR_H_

Generated by: LCOV version 1.10