// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_TORQUE_IMPLEMENTATION_VISITOR_H_
#define V8_TORQUE_IMPLEMENTATION_VISITOR_H_

#include <memory>
#include <string>

#include "src/base/macros.h"
#include "src/torque/ast.h"
#include "src/torque/cfg.h"
#include "src/torque/declarations.h"
#include "src/torque/global-context.h"
#include "src/torque/type-oracle.h"
#include "src/torque/types.h"
#include "src/torque/utils.h"

namespace v8 {
namespace internal {
namespace torque {

template <typename T>
class Binding;
class LocalValue;
class ImplementationVisitor;

// LocationReference is the representation of an l-value, so a value that might
// allow for assignment. For uniformity, this class can also represent
// unassignable temporaries. Assignable values fall in two categories:
//   - stack ranges that represent mutable variables, including structs.
//   - field or element access expressions that generate operator calls.
class LocationReference {
 public:
  // An assignable stack range.
  static LocationReference VariableAccess(
      VisitResult variable,
      base::Optional<Binding<LocalValue>*> binding = base::nullopt) {
    DCHECK(variable.IsOnStack());
    LocationReference result;
    result.variable_ = std::move(variable);
    result.binding_ = binding;
    return result;
  }
  // An unassignable value. {description} is only used for error messages.
  static LocationReference Temporary(VisitResult temporary,
                                     std::string description) {
    LocationReference result;
    result.temporary_ = std::move(temporary);
    result.temporary_description_ = std::move(description);
    return result;
  }
  // A heap reference, that is, a tagged value and an offset to encode an inner
  // pointer.
  static LocationReference HeapReference(VisitResult heap_reference) {
    LocationReference result;
    DCHECK(TypeOracle::MatchReferenceGeneric(heap_reference.type()));
    result.heap_reference_ = std::move(heap_reference);
    return result;
  }
  // A reference to an array on the heap. That is, a tagged value, an offset to
  // encode an inner pointer, and the number of elements.
  static LocationReference HeapSlice(VisitResult heap_slice) {
    LocationReference result;
    DCHECK(Type::MatchUnaryGeneric(heap_slice.type(),
                                   TypeOracle::GetSliceGeneric()));
    result.heap_slice_ = std::move(heap_slice);
    return result;
  }
  static LocationReference ArrayAccess(VisitResult base, VisitResult offset) {
    LocationReference result;
    result.eval_function_ = std::string{"[]"};
    result.assign_function_ = std::string{"[]="};
    result.call_arguments_ = {base, offset};
    return result;
  }
  static LocationReference FieldAccess(VisitResult object,
                                       std::string fieldname) {
    LocationReference result;
    result.eval_function_ = "." + fieldname;
    result.assign_function_ = "." + fieldname + "=";
    result.call_arguments_ = {object};
    return result;
  }
  static LocationReference BitFieldAccess(const LocationReference& object,
                                          BitField field) {
    LocationReference result;
    result.bit_field_struct_ = std::make_shared<LocationReference>(object);
    result.bit_field_ = std::move(field);
    return result;
  }

  bool IsConst() const {
    if (IsHeapReference()) {
      bool is_const;
      bool success =
          TypeOracle::MatchReferenceGeneric(heap_reference().type(), &is_const)
              .has_value();
      CHECK(success);
      return is_const;
    }
    return IsTemporary();
  }

  bool IsVariableAccess() const { return variable_.has_value(); }
  const VisitResult& variable() const {
    DCHECK(IsVariableAccess());
    return *variable_;
  }
  bool IsTemporary() const { return temporary_.has_value(); }
  const VisitResult& temporary() const {
    DCHECK(IsTemporary());
    return *temporary_;
  }
  bool IsHeapReference() const { return heap_reference_.has_value(); }
  const VisitResult& heap_reference() const {
    DCHECK(IsHeapReference());
    return *heap_reference_;
  }
  bool IsHeapSlice() const { return heap_slice_.has_value(); }
  const VisitResult& heap_slice() const {
    DCHECK(IsHeapSlice());
    return *heap_slice_;
  }
  bool IsBitFieldAccess() const {
    bool is_bitfield_access = bit_field_struct_ != nullptr;
    DCHECK_EQ(is_bitfield_access, bit_field_.has_value());
    return is_bitfield_access;
  }
  const LocationReference& bit_field_struct_location() const {
    DCHECK(IsBitFieldAccess());
    return *bit_field_struct_;
  }
  const BitField& bit_field() const {
    DCHECK(IsBitFieldAccess());
    return *bit_field_;
  }

  base::Optional<const Type*> ReferencedType() const {
    if (IsHeapReference()) {
      return *TypeOracle::MatchReferenceGeneric(heap_reference().type());
    }
    if (IsHeapSlice()) {
      return *Type::MatchUnaryGeneric(heap_slice().type(),
                                      TypeOracle::GetSliceGeneric());
    }
    if (IsBitFieldAccess()) {
      return bit_field_->name_and_type.type;
    }
    if (IsVariableAccess() || IsHeapSlice() || IsTemporary()) {
      return GetVisitResult().type();
    }
    return base::nullopt;
  }

  const VisitResult& GetVisitResult() const {
    if (IsVariableAccess()) return variable();
    if (IsHeapSlice()) return heap_slice();
    DCHECK(IsTemporary());
    return temporary();
  }

  // For error reporting.
  const std::string& temporary_description() const {
    DCHECK(IsTemporary());
    return *temporary_description_;
  }

  bool IsCallAccess() const {
    bool is_call_access = eval_function_.has_value();
    DCHECK_EQ(is_call_access, assign_function_.has_value());
    return is_call_access;
  }
  const VisitResultVector& call_arguments() const {
    DCHECK(IsCallAccess());
    return call_arguments_;
  }
  const std::string& eval_function() const {
    DCHECK(IsCallAccess());
    return *eval_function_;
  }
  const std::string& assign_function() const {
    DCHECK(IsCallAccess());
    return *assign_function_;
  }
  base::Optional<Binding<LocalValue>*> binding() const {
    DCHECK(IsVariableAccess());
    return binding_;
  }

 private:
  base::Optional<VisitResult> variable_;
  base::Optional<VisitResult> temporary_;
  base::Optional<std::string> temporary_description_;
  base::Optional<VisitResult> heap_reference_;
  base::Optional<VisitResult> heap_slice_;
  base::Optional<std::string> eval_function_;
  base::Optional<std::string> assign_function_;
  VisitResultVector call_arguments_;
  base::Optional<Binding<LocalValue>*> binding_;

  // The location of the bitfield struct that contains this bitfield, if this
  // reference is a bitfield access. Uses a shared_ptr so that LocationReference
  // is copyable, allowing us to set this field equal to a copy of a
  // stack-allocated LocationReference.
  std::shared_ptr<const LocationReference> bit_field_struct_;
  base::Optional<BitField> bit_field_;

  LocationReference() = default;
};

struct InitializerResults {
  std::vector<Identifier*> names;
  std::map<std::string, VisitResult> field_value_map;
};

struct LayoutForInitialization {
  std::map<std::string, VisitResult> array_lengths;
  std::map<std::string, VisitResult> offsets;
  VisitResult size;
};

template <class T>
class Binding;

template <class T>
class BindingsManager {
 public:
  base::Optional<Binding<T>*> TryLookup(const std::string& name) {
    if (name.length() >= 2 && name[0] == '_' && name[1] != '_') {
      Error("Trying to reference '", name, "' which is marked as unused.")
          .Throw();
    }
    auto binding = current_bindings_[name];
    if (binding) {
      (*binding)->SetUsed();
    }
    return binding;
  }

 private:
  friend class Binding<T>;
  std::unordered_map<std::string, base::Optional<Binding<T>*>>
      current_bindings_;
};

template <class T>
class Binding : public T {
 public:
  template <class... Args>
  Binding(BindingsManager<T>* manager, const std::string& name, Args&&... args)
      : T(std::forward<Args>(args)...),
        manager_(manager),
        name_(name),
        previous_binding_(this),
        used_(false),
        written_(false) {
    std::swap(previous_binding_, manager_->current_bindings_[name]);
  }
  template <class... Args>
  Binding(BindingsManager<T>* manager, const Identifier* name, Args&&... args)
      : Binding(manager, name->value, std::forward<Args>(args)...) {
    declaration_position_ = name->pos;
  }
  ~Binding() {
    if (!used_ && !SkipLintCheck()) {
      Lint(BindingTypeString(), "'", name_,
           "' is never used. Prefix with '_' if this is intentional.")
          .Position(declaration_position_);
    }

    if (CheckWritten() && !written_ && !SkipLintCheck()) {
      Lint(BindingTypeString(), "'", name_,
           "' is never assigned to. Use 'const' instead of 'let'.")
          .Position(declaration_position_);
    }

    manager_->current_bindings_[name_] = previous_binding_;
  }

  std::string BindingTypeString() const;
  bool CheckWritten() const;

  const std::string& name() const { return name_; }
  SourcePosition declaration_position() const { return declaration_position_; }

  bool Used() const { return used_; }
  void SetUsed() { used_ = true; }

  bool Written() const { return written_; }
  void SetWritten() { written_ = true; }

 private:
  bool SkipLintCheck() const { return name_.length() > 0 && name_[0] == '_'; }

  BindingsManager<T>* manager_;
  const std::string name_;
  base::Optional<Binding*> previous_binding_;
  SourcePosition declaration_position_ = CurrentSourcePosition::Get();
  bool used_;
  bool written_;
  DISALLOW_COPY_AND_ASSIGN(Binding);
};

template <class T>
class BlockBindings {
 public:
  explicit BlockBindings(BindingsManager<T>* manager) : manager_(manager) {}
  void Add(std::string name, T value, bool mark_as_used = false) {
    ReportErrorIfAlreadyBound(name);
    auto binding =
        std::make_unique<Binding<T>>(manager_, name, std::move(value));
    if (mark_as_used) binding->SetUsed();
    bindings_.push_back(std::move(binding));
  }

  void Add(const Identifier* name, T value, bool mark_as_used = false) {
    ReportErrorIfAlreadyBound(name->value);
    auto binding =
        std::make_unique<Binding<T>>(manager_, name, std::move(value));
    if (mark_as_used) binding->SetUsed();
    bindings_.push_back(std::move(binding));
  }

  std::vector<Binding<T>*> bindings() const {
    std::vector<Binding<T>*> result;
    result.reserve(bindings_.size());
    for (auto& b : bindings_) {
      result.push_back(b.get());
    }
    return result;
  }

 private:
  void ReportErrorIfAlreadyBound(const std::string& name) {
    for (const auto& binding : bindings_) {
      if (binding->name() == name) {
        ReportError(
            "redeclaration of name \"", name,
            "\" in the same block is illegal, previous declaration at: ",
            binding->declaration_position());
      }
    }
  }

  BindingsManager<T>* manager_;
  std::vector<std::unique_ptr<Binding<T>>> bindings_;
};

class LocalValue {
 public:
  explicit LocalValue(LocationReference reference)
      : value(std::move(reference)) {}
  explicit LocalValue(std::string inaccessible_explanation)
      : inaccessible_explanation(std::move(inaccessible_explanation)) {}

  LocationReference GetLocationReference(Binding<LocalValue>* binding) {
    if (value) {
      const LocationReference& ref = *value;
      if (ref.IsVariableAccess()) {
        // Attach the binding to enable the never-assigned-to lint check.
        return LocationReference::VariableAccess(ref.GetVisitResult(), binding);
      }
      return ref;
    } else {
      Error("Cannot access ", binding->name(), ": ", inaccessible_explanation)
          .Throw();
    }
  }

  bool IsAccessible() const { return value.has_value(); }

 private:
  base::Optional<LocationReference> value;
  std::string inaccessible_explanation;
};

struct LocalLabel {
  Block* block;
  std::vector<const Type*> parameter_types;

  explicit LocalLabel(Block* block,
                      std::vector<const Type*> parameter_types = {})
      : block(block), parameter_types(std::move(parameter_types)) {}
};

template <>
inline std::string Binding<LocalValue>::BindingTypeString() const {
  return "Variable ";
}
template <>
inline bool Binding<LocalValue>::CheckWritten() const {
  // Do the check only for non-const variables and non struct types.
  auto binding = *manager_->current_bindings_[name_];
  if (!binding->IsAccessible()) return false;
  const LocationReference& ref = binding->GetLocationReference(binding);
  if (!ref.IsVariableAccess()) return false;
  return !ref.GetVisitResult().type()->StructSupertype();
}
template <>
inline std::string Binding<LocalLabel>::BindingTypeString() const {
  return "Label ";
}
template <>
inline bool Binding<LocalLabel>::CheckWritten() const {
  return false;
}

struct Arguments {
  VisitResultVector parameters;
  std::vector<Binding<LocalLabel>*> labels;
};

// Determine if a callable should be considered as an overload.
bool IsCompatibleSignature(const Signature& sig, const TypeVector& types,
                           size_t label_count);

class ImplementationVisitor {
 public:
  void GenerateBuiltinDefinitionsAndInterfaceDescriptors(
      const std::string& output_directory);
  void GenerateClassFieldOffsets(const std::string& output_directory);
  void GenerateBitFields(const std::string& output_directory);
  void GeneratePrintDefinitions(const std::string& output_directory);
  void GenerateClassDefinitions(const std::string& output_directory);
  void GenerateBodyDescriptors(const std::string& output_directory);
  void GenerateInstanceTypes(const std::string& output_directory);
  void GenerateClassVerifiers(const std::string& output_directory);
  void GenerateEnumVerifiers(const std::string& output_directory);
  void GenerateClassDebugReaders(const std::string& output_directory);
  void GenerateExportedMacrosAssembler(const std::string& output_directory);
  void GenerateCSATypes(const std::string& output_directory);

  VisitResult Visit(Expression* expr);
  const Type* Visit(Statement* stmt);

  template <typename T>
  void CheckInitializersWellformed(
      const std::string& aggregate_name, const std::vector<T>& aggregate_fields,
      const std::vector<NameAndExpression>& initializers,
      bool ignore_first_field = false) {
    size_t fields_offset = ignore_first_field ? 1 : 0;
    size_t fields_size = aggregate_fields.size() - fields_offset;
    for (size_t i = 0; i < std::min(fields_size, initializers.size()); i++) {
      const std::string& field_name =
          aggregate_fields[i + fields_offset].name_and_type.name;
      Identifier* found_name = initializers[i].name;
      if (field_name != found_name->value) {
        Error("Expected field name \"", field_name, "\" instead of \"",
              found_name->value, "\"")
            .Position(found_name->pos)
            .Throw();
      }
    }
    if (fields_size != initializers.size()) {
      ReportError("expected ", fields_size, " initializers for ",
                  aggregate_name, " found ", initializers.size());
    }
  }

  InitializerResults VisitInitializerResults(
      const ClassType* class_type,
      const std::vector<NameAndExpression>& expressions);
  LocationReference GenerateFieldReference(VisitResult object,
                                           const Field& field,
                                           const ClassType* class_type);
  LocationReference GenerateFieldReferenceForInit(
      VisitResult object, const Field& field,
      const LayoutForInitialization& layout);
  VisitResult GenerateArrayLength(
      Expression* array_length, Namespace* nspace,
      const std::map<std::string, LocalValue>& bindings);
  VisitResult GenerateArrayLength(VisitResult object, const Field& field);
  VisitResult GenerateArrayLength(const ClassType* class_type,
                                  const InitializerResults& initializer_results,
                                  const Field& field);
  LayoutForInitialization GenerateLayoutForInitialization(
      const ClassType* class_type,
      const InitializerResults& initializer_results);

  void InitializeClass(const ClassType* class_type, VisitResult allocate_result,
                       const InitializerResults& initializer_results,
                       const LayoutForInitialization& layout);

  VisitResult Visit(StructExpression* decl);

  LocationReference GetLocationReference(Expression* location);
  LocationReference LookupLocalValue(const std::string& name);
  LocationReference GetLocationReference(IdentifierExpression* expr);
  LocationReference GetLocationReference(DereferenceExpression* expr);
  LocationReference GetLocationReference(FieldAccessExpression* expr);
  LocationReference GenerateFieldAccess(
      LocationReference reference, const std::string& fieldname,
      bool ignore_stuct_field_constness = false,
      base::Optional<SourcePosition> pos = {});
  LocationReference GetLocationReference(ElementAccessExpression* expr);

  VisitResult GenerateFetchFromLocation(const LocationReference& reference);

  VisitResult GetBuiltinCode(Builtin* builtin);

  VisitResult Visit(LocationExpression* expr);
  VisitResult Visit(FieldAccessExpression* expr);

  void VisitAllDeclarables();
  void Visit(Declarable* delarable);
  void Visit(TypeAlias* decl);
  VisitResult InlineMacro(Macro* macro,
                          base::Optional<LocationReference> this_reference,
                          const std::vector<VisitResult>& arguments,
                          const std::vector<Block*> label_blocks);
  void VisitMacroCommon(Macro* macro);
  void Visit(ExternMacro* macro) {}
  void Visit(TorqueMacro* macro);
  void Visit(Method* macro);
  void Visit(Builtin* builtin);
  void Visit(NamespaceConstant* decl);

  VisitResult Visit(CallExpression* expr, bool is_tail = false);
  VisitResult Visit(CallMethodExpression* expr);
  VisitResult Visit(IntrinsicCallExpression* intrinsic);
  const Type* Visit(TailCallStatement* stmt);

  VisitResult Visit(ConditionalExpression* expr);

  VisitResult Visit(LogicalOrExpression* expr);
  VisitResult Visit(LogicalAndExpression* expr);

  VisitResult Visit(IncrementDecrementExpression* expr);
  VisitResult Visit(AssignmentExpression* expr);
  VisitResult Visit(StringLiteralExpression* expr);
  VisitResult Visit(NumberLiteralExpression* expr);
  VisitResult Visit(AssumeTypeImpossibleExpression* expr);
  VisitResult Visit(TryLabelExpression* expr);
  VisitResult Visit(StatementExpression* expr);
  VisitResult Visit(NewExpression* expr);
  VisitResult Visit(SpreadExpression* expr);

  const Type* Visit(ReturnStatement* stmt);
  const Type* Visit(GotoStatement* stmt);
  const Type* Visit(IfStatement* stmt);
  const Type* Visit(WhileStatement* stmt);
  const Type* Visit(BreakStatement* stmt);
  const Type* Visit(ContinueStatement* stmt);
  const Type* Visit(ForLoopStatement* stmt);
  const Type* Visit(VarDeclarationStatement* stmt);
  const Type* Visit(VarDeclarationStatement* stmt,
                    BlockBindings<LocalValue>* block_bindings);
  const Type* Visit(BlockStatement* block);
  const Type* Visit(ExpressionStatement* stmt);
  const Type* Visit(DebugStatement* stmt);
  const Type* Visit(AssertStatement* stmt);

  void BeginGeneratedFiles();
  void EndGeneratedFiles();
  // TODO(tebbi): Switch to per-file generation for runtime macros and merge
  // these functions into {Begin,End}GeneratedFiles().
  void BeginRuntimeMacrosFile();
  void EndRuntimeMacrosFile();

  void GenerateImplementation(const std::string& dir);

  DECLARE_CONTEXTUAL_VARIABLE(ValueBindingsManager,
                              BindingsManager<LocalValue>);
  DECLARE_CONTEXTUAL_VARIABLE(LabelBindingsManager,
                              BindingsManager<LocalLabel>);
  DECLARE_CONTEXTUAL_VARIABLE(CurrentCallable, Callable*);
  DECLARE_CONTEXTUAL_VARIABLE(CurrentFileStreams,
                              GlobalContext::PerFileStreams*);
  DECLARE_CONTEXTUAL_VARIABLE(CurrentReturnValue, base::Optional<VisitResult>);

  // A BindingsManagersScope has to be active for local bindings to be created.
  // Shadowing an existing BindingsManagersScope by creating a new one hides all
  // existing bindings while the additional BindingsManagersScope is active.
  struct BindingsManagersScope {
    ValueBindingsManager::Scope value_bindings_manager;
    LabelBindingsManager::Scope label_bindings_manager;
  };

  void SetDryRun(bool is_dry_run) { is_dry_run_ = is_dry_run; }

 private:
  base::Optional<Block*> GetCatchBlock();
  void GenerateCatchBlock(base::Optional<Block*> catch_block);

  // {StackScope} records the stack height at creation time and reconstructs it
  // when being destructed by emitting a {DeleteRangeInstruction}, except for
  // the slots protected by {StackScope::Yield}. Calling {Yield(v)} deletes all
  // slots above the initial stack height except for the slots of {v}, which are
  // moved to form the only slots above the initial height and marks them to
  // survive destruction of the {StackScope}. A typical pattern is the
  // following:
  //
  // VisitResult result;
  // {
  //   StackScope stack_scope(this);
  //   // ... create temporary slots ...
  //   result = stack_scope.Yield(surviving_slots);
  // }
  class StackScope {
   public:
    explicit StackScope(ImplementationVisitor* visitor) : visitor_(visitor) {
      base_ = visitor_->assembler().CurrentStack().AboveTop();
    }
    VisitResult Yield(VisitResult result) {
      DCHECK(!closed_);
      closed_ = true;
      if (!result.IsOnStack()) {
        if (!visitor_->assembler().CurrentBlockIsComplete()) {
          visitor_->assembler().DropTo(base_);
        }
        return result;
      }
      DCHECK_LE(base_, result.stack_range().begin());
      DCHECK_LE(result.stack_range().end(),
                visitor_->assembler().CurrentStack().AboveTop());
      visitor_->assembler().DropTo(result.stack_range().end());
      visitor_->assembler().DeleteRange(
          StackRange{base_, result.stack_range().begin()});
      base_ = visitor_->assembler().CurrentStack().AboveTop();
      return VisitResult(result.type(), visitor_->assembler().TopRange(
                                            result.stack_range().Size()));
    }

    void Close() {
      DCHECK(!closed_);
      closed_ = true;
      if (!visitor_->assembler().CurrentBlockIsComplete()) {
        visitor_->assembler().DropTo(base_);
      }
    }

    ~StackScope() {
      if (closed_) {
        DCHECK_IMPLIES(
            !visitor_->assembler().CurrentBlockIsComplete(),
            base_ == visitor_->assembler().CurrentStack().AboveTop());
      } else {
        Close();
      }
    }

   private:
    ImplementationVisitor* visitor_;
    BottomOffset base_;
    bool closed_ = false;
  };

  class BreakContinueActivator {
   public:
    BreakContinueActivator(Block* break_block, Block* continue_block)
        : break_binding_{&LabelBindingsManager::Get(), kBreakLabelName,
                         LocalLabel{break_block}},
          continue_binding_{&LabelBindingsManager::Get(), kContinueLabelName,
                            LocalLabel{continue_block}} {}

   private:
    Binding<LocalLabel> break_binding_;
    Binding<LocalLabel> continue_binding_;
  };

  base::Optional<Binding<LocalValue>*> TryLookupLocalValue(
      const std::string& name);
  base::Optional<Binding<LocalLabel>*> TryLookupLabel(const std::string& name);
  Binding<LocalLabel>* LookupLabel(const std::string& name);
  Block* LookupSimpleLabel(const std::string& name);
  template <class Container>
  Callable* LookupCallable(const QualifiedName& name,
                           const Container& declaration_container,
                           const TypeVector& types,
                           const std::vector<Binding<LocalLabel>*>& labels,
                           const TypeVector& specialization_types,
                           bool silence_errors = false);
  bool TestLookupCallable(const QualifiedName& name,
                          const TypeVector& parameter_types);

  template <class Container>
  Callable* LookupCallable(const QualifiedName& name,
                           const Container& declaration_container,
                           const Arguments& arguments,
                           const TypeVector& specialization_types);

  Method* LookupMethod(const std::string& name,
                       const AggregateType* receiver_type,
                       const Arguments& arguments,
                       const TypeVector& specialization_types);

  TypeArgumentInference InferSpecializationTypes(
      GenericCallable* generic, const TypeVector& explicit_specialization_types,
      const TypeVector& explicit_arguments);

  const Type* GetCommonType(const Type* left, const Type* right);

  VisitResult GenerateCopy(const VisitResult& to_copy);

  void GenerateAssignToLocation(const LocationReference& reference,
                                const VisitResult& assignment_value);

  void AddCallParameter(Callable* callable, VisitResult parameter,
                        const Type* parameter_type,
                        std::vector<VisitResult>* converted_arguments,
                        StackRange* argument_range,
                        std::vector<std::string>* constexpr_arguments,
                        bool inline_macro);

  VisitResult GenerateCall(Callable* callable,
                           base::Optional<LocationReference> this_parameter,
                           Arguments parameters,
                           const TypeVector& specialization_types = {},
                           bool tail_call = false);
  VisitResult GenerateCall(const QualifiedName& callable_name,
                           Arguments parameters,
                           const TypeVector& specialization_types = {},
                           bool tail_call = false);
  VisitResult GenerateCall(std::string callable_name, Arguments parameters,
                           const TypeVector& specialization_types = {},
                           bool tail_call = false) {
    return GenerateCall(QualifiedName(std::move(callable_name)),
                        std::move(parameters), specialization_types, tail_call);
  }
  VisitResult GeneratePointerCall(Expression* callee,
                                  const Arguments& parameters, bool tail_call);

  void GenerateBranch(const VisitResult& condition, Block* true_block,
                      Block* false_block);

  VisitResult GenerateBoolConstant(bool constant);

  void GenerateExpressionBranch(Expression* expression, Block* true_block,
                                Block* false_block);

  void GenerateMacroFunctionDeclaration(std::ostream& o,
                                        Macro* macro);
  std::vector<std::string> GenerateFunctionDeclaration(
      std::ostream& o, const std::string& macro_prefix, const std::string& name,
      const Signature& signature, const NameVector& parameter_names,
      bool pass_code_assembler_state = true);

  VisitResult GenerateImplicitConvert(const Type* destination_type,
                                      VisitResult source);

  StackRange GenerateLabelGoto(LocalLabel* label,
                               base::Optional<StackRange> arguments = {});

  VisitResult GenerateSetBitField(const Type* bitfield_struct_type,
                                  const BitField& bitfield,
                                  VisitResult bitfield_struct,
                                  VisitResult value,
                                  bool starts_as_zero = false);

  std::vector<Binding<LocalLabel>*> LabelsFromIdentifiers(
      const std::vector<Identifier*>& names);

  StackRange LowerParameter(const Type* type, const std::string& parameter_name,
                            Stack<std::string>* lowered_parameters);

  void LowerLabelParameter(const Type* type, const std::string& parameter_name,
                           std::vector<std::string>* lowered_parameters);

  std::string ExternalLabelName(const std::string& label_name);
  std::string ExternalLabelParameterName(const std::string& label_name,
                                         size_t i);
  std::string ExternalParameterName(const std::string& name);

  std::ostream& csa_ccfile() {
    if (auto* streams = CurrentFileStreams::Get()) {
      return output_type_ == OutputType::kCSA ? streams->csa_ccfile
                                              : runtime_macros_cc_;
    }
    return null_stream_;
  }
  std::ostream& csa_headerfile() {
    if (auto* streams = CurrentFileStreams::Get()) {
      return output_type_ == OutputType::kCSA ? streams->csa_headerfile
                                              : runtime_macros_h_;
    }
    return null_stream_;
  }
  std::ostream& class_definition_headerfile() {
    if (auto* streams = CurrentFileStreams::Get()) {
      return streams->class_definition_headerfile;
    }
    return null_stream_;
  }
  std::ostream& class_definition_inline_headerfile() {
    if (auto* streams = CurrentFileStreams::Get()) {
      return streams->class_definition_inline_headerfile;
    }
    return null_stream_;
  }
  std::ostream& class_definition_ccfile() {
    if (auto* streams = CurrentFileStreams::Get()) {
      return streams->class_definition_ccfile;
    }
    return null_stream_;
  }

  CfgAssembler& assembler() { return *assembler_; }

  void SetReturnValue(VisitResult return_value) {
    base::Optional<VisitResult>& current_return_value =
        CurrentReturnValue::Get();
    DCHECK_IMPLIES(current_return_value, *current_return_value == return_value);
    current_return_value = std::move(return_value);
  }

  VisitResult GetAndClearReturnValue() {
    VisitResult return_value = *CurrentReturnValue::Get();
    CurrentReturnValue::Get() = base::nullopt;
    return return_value;
  }

  void WriteFile(const std::string& file, const std::string& content) {
    if (is_dry_run_) return;
    ReplaceFileContentsIfDifferent(file, content);
  }

  const Identifier* TryGetSourceForBitfieldExpression(
      const Expression* expr) const {
    auto it = bitfield_expressions_.find(expr);
    if (it == bitfield_expressions_.end()) return nullptr;
    return it->second;
  }

  void PropagateBitfieldMark(const Expression* original,
                             const Expression* derived) {
    if (const Identifier* source =
            TryGetSourceForBitfieldExpression(original)) {
      bitfield_expressions_[derived] = source;
    }
  }

  base::Optional<CfgAssembler> assembler_;
  NullOStream null_stream_;
  bool is_dry_run_;

  // Just for allowing us to emit warnings. After visiting an Expression, if
  // that Expression is a bitfield load, plus an optional inversion or an
  // equality check with a constant, then that Expression will be present in
  // this map. The Identifier associated is the bitfield struct that contains
  // the value to load.
  std::unordered_map<const Expression*, const Identifier*>
      bitfield_expressions_;

  // The contents of the runtime macros output files. These contain all Torque
  // macros that have been generated using the C++ backend. They're not yet
  // split per source file like CSA macros, but eventually we should change them
  // to generate -inl.inc files so that callers can easily inline their
  // contents.
  std::stringstream runtime_macros_cc_;
  std::stringstream runtime_macros_h_;

  OutputType output_type_ = OutputType::kCSA;
};

void ReportAllUnusedMacros();

}  // namespace torque
}  // namespace internal
}  // namespace v8

#endif  // V8_TORQUE_IMPLEMENTATION_VISITOR_H_
