11cb0ef41Sopenharmony_ci// Copyright 2014 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef V8_COMPILER_BACKEND_CODE_GENERATOR_H_
61cb0ef41Sopenharmony_ci#define V8_COMPILER_BACKEND_CODE_GENERATOR_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <memory>
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include "src/base/optional.h"
111cb0ef41Sopenharmony_ci#include "src/codegen/macro-assembler.h"
121cb0ef41Sopenharmony_ci#include "src/codegen/optimized-compilation-info.h"
131cb0ef41Sopenharmony_ci#include "src/codegen/safepoint-table.h"
141cb0ef41Sopenharmony_ci#include "src/codegen/source-position-table.h"
151cb0ef41Sopenharmony_ci#include "src/compiler/backend/gap-resolver.h"
161cb0ef41Sopenharmony_ci#include "src/compiler/backend/instruction.h"
171cb0ef41Sopenharmony_ci#include "src/compiler/backend/unwinding-info-writer.h"
181cb0ef41Sopenharmony_ci#include "src/compiler/osr.h"
191cb0ef41Sopenharmony_ci#include "src/deoptimizer/deoptimizer.h"
201cb0ef41Sopenharmony_ci#include "src/objects/code-kind.h"
211cb0ef41Sopenharmony_ci#include "src/trap-handler/trap-handler.h"
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_cinamespace v8 {
241cb0ef41Sopenharmony_cinamespace internal {
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_cinamespace compiler {
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci// Forward declarations.
291cb0ef41Sopenharmony_ciclass DeoptimizationExit;
301cb0ef41Sopenharmony_ciclass FrameAccessState;
311cb0ef41Sopenharmony_ciclass Linkage;
321cb0ef41Sopenharmony_ciclass OutOfLineCode;
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_cistruct BranchInfo {
351cb0ef41Sopenharmony_ci  FlagsCondition condition;
361cb0ef41Sopenharmony_ci  Label* true_label;
371cb0ef41Sopenharmony_ci  Label* false_label;
381cb0ef41Sopenharmony_ci  bool fallthru;
391cb0ef41Sopenharmony_ci};
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ciclass InstructionOperandIterator {
421cb0ef41Sopenharmony_ci public:
431cb0ef41Sopenharmony_ci  InstructionOperandIterator(Instruction* instr, size_t pos)
441cb0ef41Sopenharmony_ci      : instr_(instr), pos_(pos) {}
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci  Instruction* instruction() const { return instr_; }
471cb0ef41Sopenharmony_ci  InstructionOperand* Advance() { return instr_->InputAt(pos_++); }
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci private:
501cb0ef41Sopenharmony_ci  Instruction* instr_;
511cb0ef41Sopenharmony_ci  size_t pos_;
521cb0ef41Sopenharmony_ci};
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_cienum class DeoptimizationLiteralKind { kObject, kNumber, kString, kInvalid };
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci// Either a non-null Handle<Object>, a double or a StringConstantBase.
571cb0ef41Sopenharmony_ciclass DeoptimizationLiteral {
581cb0ef41Sopenharmony_ci public:
591cb0ef41Sopenharmony_ci  DeoptimizationLiteral()
601cb0ef41Sopenharmony_ci      : kind_(DeoptimizationLiteralKind::kInvalid),
611cb0ef41Sopenharmony_ci        object_(),
621cb0ef41Sopenharmony_ci        number_(0),
631cb0ef41Sopenharmony_ci        string_(nullptr) {}
641cb0ef41Sopenharmony_ci  explicit DeoptimizationLiteral(Handle<Object> object)
651cb0ef41Sopenharmony_ci      : kind_(DeoptimizationLiteralKind::kObject), object_(object) {
661cb0ef41Sopenharmony_ci    CHECK(!object_.is_null());
671cb0ef41Sopenharmony_ci  }
681cb0ef41Sopenharmony_ci  explicit DeoptimizationLiteral(double number)
691cb0ef41Sopenharmony_ci      : kind_(DeoptimizationLiteralKind::kNumber), number_(number) {}
701cb0ef41Sopenharmony_ci  explicit DeoptimizationLiteral(const StringConstantBase* string)
711cb0ef41Sopenharmony_ci      : kind_(DeoptimizationLiteralKind::kString), string_(string) {}
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci  Handle<Object> object() const { return object_; }
741cb0ef41Sopenharmony_ci  const StringConstantBase* string() const { return string_; }
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci  bool operator==(const DeoptimizationLiteral& other) const {
771cb0ef41Sopenharmony_ci    return kind_ == other.kind_ && object_.equals(other.object_) &&
781cb0ef41Sopenharmony_ci           bit_cast<uint64_t>(number_) == bit_cast<uint64_t>(other.number_) &&
791cb0ef41Sopenharmony_ci           bit_cast<intptr_t>(string_) == bit_cast<intptr_t>(other.string_);
801cb0ef41Sopenharmony_ci  }
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci  Handle<Object> Reify(Isolate* isolate) const;
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci  void Validate() const {
851cb0ef41Sopenharmony_ci    CHECK_NE(kind_, DeoptimizationLiteralKind::kInvalid);
861cb0ef41Sopenharmony_ci  }
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci  DeoptimizationLiteralKind kind() const {
891cb0ef41Sopenharmony_ci    Validate();
901cb0ef41Sopenharmony_ci    return kind_;
911cb0ef41Sopenharmony_ci  }
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci private:
941cb0ef41Sopenharmony_ci  DeoptimizationLiteralKind kind_;
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci  Handle<Object> object_;
971cb0ef41Sopenharmony_ci  double number_ = 0;
981cb0ef41Sopenharmony_ci  const StringConstantBase* string_ = nullptr;
991cb0ef41Sopenharmony_ci};
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci// These structs hold pc offsets for generated instructions and is only used
1021cb0ef41Sopenharmony_ci// when tracing for turbolizer is enabled.
1031cb0ef41Sopenharmony_cistruct TurbolizerCodeOffsetsInfo {
1041cb0ef41Sopenharmony_ci  int code_start_register_check = -1;
1051cb0ef41Sopenharmony_ci  int deopt_check = -1;
1061cb0ef41Sopenharmony_ci  int blocks_start = -1;
1071cb0ef41Sopenharmony_ci  int out_of_line_code = -1;
1081cb0ef41Sopenharmony_ci  int deoptimization_exits = -1;
1091cb0ef41Sopenharmony_ci  int pools = -1;
1101cb0ef41Sopenharmony_ci  int jump_tables = -1;
1111cb0ef41Sopenharmony_ci};
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_cistruct TurbolizerInstructionStartInfo {
1141cb0ef41Sopenharmony_ci  int gap_pc_offset = -1;
1151cb0ef41Sopenharmony_ci  int arch_instr_pc_offset = -1;
1161cb0ef41Sopenharmony_ci  int condition_pc_offset = -1;
1171cb0ef41Sopenharmony_ci};
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci// Generates native code for a sequence of instructions.
1201cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE CodeGenerator final : public GapResolver::Assembler {
1211cb0ef41Sopenharmony_ci public:
1221cb0ef41Sopenharmony_ci  explicit CodeGenerator(Zone* codegen_zone, Frame* frame, Linkage* linkage,
1231cb0ef41Sopenharmony_ci                         InstructionSequence* instructions,
1241cb0ef41Sopenharmony_ci                         OptimizedCompilationInfo* info, Isolate* isolate,
1251cb0ef41Sopenharmony_ci                         base::Optional<OsrHelper> osr_helper,
1261cb0ef41Sopenharmony_ci                         int start_source_position,
1271cb0ef41Sopenharmony_ci                         JumpOptimizationInfo* jump_opt,
1281cb0ef41Sopenharmony_ci                         const AssemblerOptions& options, Builtin builtin,
1291cb0ef41Sopenharmony_ci                         size_t max_unoptimized_frame_height,
1301cb0ef41Sopenharmony_ci                         size_t max_pushed_argument_count,
1311cb0ef41Sopenharmony_ci                         const char* debug_name = nullptr);
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci  // Generate native code. After calling AssembleCode, call FinalizeCode to
1341cb0ef41Sopenharmony_ci  // produce the actual code object. If an error occurs during either phase,
1351cb0ef41Sopenharmony_ci  // FinalizeCode returns an empty MaybeHandle.
1361cb0ef41Sopenharmony_ci  void AssembleCode();  // Does not need to run on main thread.
1371cb0ef41Sopenharmony_ci  MaybeHandle<Code> FinalizeCode();
1381cb0ef41Sopenharmony_ci
1391cb0ef41Sopenharmony_ci  base::OwnedVector<byte> GetSourcePositionTable();
1401cb0ef41Sopenharmony_ci  base::OwnedVector<byte> GetProtectedInstructionsData();
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci  InstructionSequence* instructions() const { return instructions_; }
1431cb0ef41Sopenharmony_ci  FrameAccessState* frame_access_state() const { return frame_access_state_; }
1441cb0ef41Sopenharmony_ci  const Frame* frame() const { return frame_access_state_->frame(); }
1451cb0ef41Sopenharmony_ci  Isolate* isolate() const { return isolate_; }
1461cb0ef41Sopenharmony_ci  Linkage* linkage() const { return linkage_; }
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci  Label* GetLabel(RpoNumber rpo) { return &labels_[rpo.ToSize()]; }
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci  void AddProtectedInstructionLanding(uint32_t instr_offset,
1511cb0ef41Sopenharmony_ci                                      uint32_t landing_offset);
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ci  bool wasm_runtime_exception_support() const;
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci  SourcePosition start_source_position() const {
1561cb0ef41Sopenharmony_ci    return start_source_position_;
1571cb0ef41Sopenharmony_ci  }
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci  void AssembleSourcePosition(Instruction* instr);
1601cb0ef41Sopenharmony_ci  void AssembleSourcePosition(SourcePosition source_position);
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci  // Record a safepoint with the given pointer map.
1631cb0ef41Sopenharmony_ci  void RecordSafepoint(ReferenceMap* references);
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ci  Zone* zone() const { return zone_; }
1661cb0ef41Sopenharmony_ci  TurboAssembler* tasm() { return &tasm_; }
1671cb0ef41Sopenharmony_ci  SafepointTableBuilder* safepoint_table_builder() { return &safepoints_; }
1681cb0ef41Sopenharmony_ci  size_t handler_table_offset() const { return handler_table_offset_; }
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci  const ZoneVector<int>& block_starts() const { return block_starts_; }
1711cb0ef41Sopenharmony_ci  const ZoneVector<TurbolizerInstructionStartInfo>& instr_starts() const {
1721cb0ef41Sopenharmony_ci    return instr_starts_;
1731cb0ef41Sopenharmony_ci  }
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci  const TurbolizerCodeOffsetsInfo& offsets_info() const {
1761cb0ef41Sopenharmony_ci    return offsets_info_;
1771cb0ef41Sopenharmony_ci  }
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci  static constexpr int kBinarySearchSwitchMinimalCases = 4;
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_ci  // Returns true if an offset should be applied to the given stack check. There
1821cb0ef41Sopenharmony_ci  // are two reasons that this could happen:
1831cb0ef41Sopenharmony_ci  // 1. The optimized frame is smaller than the corresponding deoptimized frames
1841cb0ef41Sopenharmony_ci  //    and an offset must be applied in order to be able to deopt safely.
1851cb0ef41Sopenharmony_ci  // 2. The current function pushes a large number of arguments to the stack.
1861cb0ef41Sopenharmony_ci  //    These are not accounted for by the initial frame setup.
1871cb0ef41Sopenharmony_ci  bool ShouldApplyOffsetToStackCheck(Instruction* instr, uint32_t* offset);
1881cb0ef41Sopenharmony_ci  uint32_t GetStackCheckOffset();
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci  CodeKind code_kind() const { return info_->code_kind(); }
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ci private:
1931cb0ef41Sopenharmony_ci  GapResolver* resolver() { return &resolver_; }
1941cb0ef41Sopenharmony_ci  SafepointTableBuilder* safepoints() { return &safepoints_; }
1951cb0ef41Sopenharmony_ci  OptimizedCompilationInfo* info() const { return info_; }
1961cb0ef41Sopenharmony_ci  OsrHelper* osr_helper() { return &(*osr_helper_); }
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_ci  // Create the FrameAccessState object. The Frame is immutable from here on.
1991cb0ef41Sopenharmony_ci  void CreateFrameAccessState(Frame* frame);
2001cb0ef41Sopenharmony_ci
2011cb0ef41Sopenharmony_ci  // Architecture - specific frame finalization.
2021cb0ef41Sopenharmony_ci  void FinishFrame(Frame* frame);
2031cb0ef41Sopenharmony_ci
2041cb0ef41Sopenharmony_ci  // Checks if {block} will appear directly after {current_block_} when
2051cb0ef41Sopenharmony_ci  // assembling code, in which case, a fall-through can be used.
2061cb0ef41Sopenharmony_ci  bool IsNextInAssemblyOrder(RpoNumber block) const;
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ci  // Check if a heap object can be materialized by loading from a heap root,
2091cb0ef41Sopenharmony_ci  // which is cheaper on some platforms than materializing the actual heap
2101cb0ef41Sopenharmony_ci  // object constant.
2111cb0ef41Sopenharmony_ci  bool IsMaterializableFromRoot(Handle<HeapObject> object,
2121cb0ef41Sopenharmony_ci                                RootIndex* index_return);
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ci  enum CodeGenResult { kSuccess, kTooManyDeoptimizationBailouts };
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ci  // Assemble instructions for the specified block.
2171cb0ef41Sopenharmony_ci  CodeGenResult AssembleBlock(const InstructionBlock* block);
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ci  // Assemble code for the specified instruction.
2201cb0ef41Sopenharmony_ci  CodeGenResult AssembleInstruction(int instruction_index,
2211cb0ef41Sopenharmony_ci                                    const InstructionBlock* block);
2221cb0ef41Sopenharmony_ci  void AssembleGaps(Instruction* instr);
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ci  // Compute branch info from given instruction. Returns a valid rpo number
2251cb0ef41Sopenharmony_ci  // if the branch is redundant, the returned rpo number point to the target
2261cb0ef41Sopenharmony_ci  // basic block.
2271cb0ef41Sopenharmony_ci  RpoNumber ComputeBranchInfo(BranchInfo* branch, Instruction* instr);
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_ci  // Returns true if a instruction is a tail call that needs to adjust the stack
2301cb0ef41Sopenharmony_ci  // pointer before execution. The stack slot index to the empty slot above the
2311cb0ef41Sopenharmony_ci  // adjusted stack pointer is returned in |slot|.
2321cb0ef41Sopenharmony_ci  bool GetSlotAboveSPBeforeTailCall(Instruction* instr, int* slot);
2331cb0ef41Sopenharmony_ci
2341cb0ef41Sopenharmony_ci  // Determines how to call helper stubs depending on the code kind.
2351cb0ef41Sopenharmony_ci  StubCallMode DetermineStubCallMode() const;
2361cb0ef41Sopenharmony_ci
2371cb0ef41Sopenharmony_ci  CodeGenResult AssembleDeoptimizerCall(DeoptimizationExit* exit);
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ci  // ===========================================================================
2401cb0ef41Sopenharmony_ci  // ============= Architecture-specific code generation methods. ==============
2411cb0ef41Sopenharmony_ci  // ===========================================================================
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ci  CodeGenResult AssembleArchInstruction(Instruction* instr);
2441cb0ef41Sopenharmony_ci  void AssembleArchJump(RpoNumber target);
2451cb0ef41Sopenharmony_ci  void AssembleArchJumpRegardlessOfAssemblyOrder(RpoNumber target);
2461cb0ef41Sopenharmony_ci  void AssembleArchBranch(Instruction* instr, BranchInfo* branch);
2471cb0ef41Sopenharmony_ci
2481cb0ef41Sopenharmony_ci  // Generates special branch for deoptimization condition.
2491cb0ef41Sopenharmony_ci  void AssembleArchDeoptBranch(Instruction* instr, BranchInfo* branch);
2501cb0ef41Sopenharmony_ci
2511cb0ef41Sopenharmony_ci  void AssembleArchBoolean(Instruction* instr, FlagsCondition condition);
2521cb0ef41Sopenharmony_ci  void AssembleArchSelect(Instruction* instr, FlagsCondition condition);
2531cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY
2541cb0ef41Sopenharmony_ci  void AssembleArchTrap(Instruction* instr, FlagsCondition condition);
2551cb0ef41Sopenharmony_ci#endif  // V8_ENABLE_WEBASSEMBLY
2561cb0ef41Sopenharmony_ci  void AssembleArchBinarySearchSwitchRange(Register input, RpoNumber def_block,
2571cb0ef41Sopenharmony_ci                                           std::pair<int32_t, Label*>* begin,
2581cb0ef41Sopenharmony_ci                                           std::pair<int32_t, Label*>* end);
2591cb0ef41Sopenharmony_ci  void AssembleArchBinarySearchSwitch(Instruction* instr);
2601cb0ef41Sopenharmony_ci  void AssembleArchTableSwitch(Instruction* instr);
2611cb0ef41Sopenharmony_ci
2621cb0ef41Sopenharmony_ci  // Generates code that checks whether the {kJavaScriptCallCodeStartRegister}
2631cb0ef41Sopenharmony_ci  // contains the expected pointer to the start of the instruction stream.
2641cb0ef41Sopenharmony_ci  void AssembleCodeStartRegisterCheck();
2651cb0ef41Sopenharmony_ci
2661cb0ef41Sopenharmony_ci  // When entering a code that is marked for deoptimization, rather continuing
2671cb0ef41Sopenharmony_ci  // with its execution, we jump to a lazy compiled code. We need to do this
2681cb0ef41Sopenharmony_ci  // because this code has already been deoptimized and needs to be unlinked
2691cb0ef41Sopenharmony_ci  // from the JS functions referring it.
2701cb0ef41Sopenharmony_ci  void BailoutIfDeoptimized();
2711cb0ef41Sopenharmony_ci
2721cb0ef41Sopenharmony_ci  // Generates an architecture-specific, descriptor-specific prologue
2731cb0ef41Sopenharmony_ci  // to set up a stack frame.
2741cb0ef41Sopenharmony_ci  void AssembleConstructFrame();
2751cb0ef41Sopenharmony_ci
2761cb0ef41Sopenharmony_ci  // Generates an architecture-specific, descriptor-specific return sequence
2771cb0ef41Sopenharmony_ci  // to tear down a stack frame.
2781cb0ef41Sopenharmony_ci  void AssembleReturn(InstructionOperand* pop);
2791cb0ef41Sopenharmony_ci
2801cb0ef41Sopenharmony_ci  void AssembleDeconstructFrame();
2811cb0ef41Sopenharmony_ci
2821cb0ef41Sopenharmony_ci  // Generates code to manipulate the stack in preparation for a tail call.
2831cb0ef41Sopenharmony_ci  void AssemblePrepareTailCall();
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_ci  enum PushTypeFlag {
2861cb0ef41Sopenharmony_ci    kImmediatePush = 0x1,
2871cb0ef41Sopenharmony_ci    kRegisterPush = 0x2,
2881cb0ef41Sopenharmony_ci    kStackSlotPush = 0x4,
2891cb0ef41Sopenharmony_ci    kScalarPush = kRegisterPush | kStackSlotPush
2901cb0ef41Sopenharmony_ci  };
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_ci  using PushTypeFlags = base::Flags<PushTypeFlag>;
2931cb0ef41Sopenharmony_ci
2941cb0ef41Sopenharmony_ci  static bool IsValidPush(InstructionOperand source, PushTypeFlags push_type);
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_ci  // Generate a list of moves from an instruction that are candidates to be
2971cb0ef41Sopenharmony_ci  // turned into push instructions on platforms that support them. In general,
2981cb0ef41Sopenharmony_ci  // the list of push candidates are moves to a set of contiguous destination
2991cb0ef41Sopenharmony_ci  // InstructionOperand locations on the stack that don't clobber values that
3001cb0ef41Sopenharmony_ci  // are needed to resolve the gap or use values generated by the gap,
3011cb0ef41Sopenharmony_ci  // i.e. moves that can be hoisted together before the actual gap and assembled
3021cb0ef41Sopenharmony_ci  // together.
3031cb0ef41Sopenharmony_ci  static void GetPushCompatibleMoves(Instruction* instr,
3041cb0ef41Sopenharmony_ci                                     PushTypeFlags push_type,
3051cb0ef41Sopenharmony_ci                                     ZoneVector<MoveOperands*>* pushes);
3061cb0ef41Sopenharmony_ci
3071cb0ef41Sopenharmony_ci  class MoveType {
3081cb0ef41Sopenharmony_ci   public:
3091cb0ef41Sopenharmony_ci    enum Type {
3101cb0ef41Sopenharmony_ci      kRegisterToRegister,
3111cb0ef41Sopenharmony_ci      kRegisterToStack,
3121cb0ef41Sopenharmony_ci      kStackToRegister,
3131cb0ef41Sopenharmony_ci      kStackToStack,
3141cb0ef41Sopenharmony_ci      kConstantToRegister,
3151cb0ef41Sopenharmony_ci      kConstantToStack
3161cb0ef41Sopenharmony_ci    };
3171cb0ef41Sopenharmony_ci
3181cb0ef41Sopenharmony_ci    // Detect what type of move or swap needs to be performed. Note that these
3191cb0ef41Sopenharmony_ci    // functions do not take into account the representation (Tagged, FP,
3201cb0ef41Sopenharmony_ci    // ...etc).
3211cb0ef41Sopenharmony_ci
3221cb0ef41Sopenharmony_ci    static Type InferMove(InstructionOperand* source,
3231cb0ef41Sopenharmony_ci                          InstructionOperand* destination);
3241cb0ef41Sopenharmony_ci    static Type InferSwap(InstructionOperand* source,
3251cb0ef41Sopenharmony_ci                          InstructionOperand* destination);
3261cb0ef41Sopenharmony_ci  };
3271cb0ef41Sopenharmony_ci  // Called before a tail call |instr|'s gap moves are assembled and allows
3281cb0ef41Sopenharmony_ci  // gap-specific pre-processing, e.g. adjustment of the sp for tail calls that
3291cb0ef41Sopenharmony_ci  // need it before gap moves or conversion of certain gap moves into pushes.
3301cb0ef41Sopenharmony_ci  void AssembleTailCallBeforeGap(Instruction* instr,
3311cb0ef41Sopenharmony_ci                                 int first_unused_stack_slot);
3321cb0ef41Sopenharmony_ci  // Called after a tail call |instr|'s gap moves are assembled and allows
3331cb0ef41Sopenharmony_ci  // gap-specific post-processing, e.g. adjustment of the sp for tail calls that
3341cb0ef41Sopenharmony_ci  // need it after gap moves.
3351cb0ef41Sopenharmony_ci  void AssembleTailCallAfterGap(Instruction* instr,
3361cb0ef41Sopenharmony_ci                                int first_unused_stack_slot);
3371cb0ef41Sopenharmony_ci
3381cb0ef41Sopenharmony_ci  void FinishCode();
3391cb0ef41Sopenharmony_ci  void MaybeEmitOutOfLineConstantPool();
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_ci  void IncrementStackAccessCounter(InstructionOperand* source,
3421cb0ef41Sopenharmony_ci                                   InstructionOperand* destination);
3431cb0ef41Sopenharmony_ci
3441cb0ef41Sopenharmony_ci  // ===========================================================================
3451cb0ef41Sopenharmony_ci  // ============== Architecture-specific gap resolver methods. ================
3461cb0ef41Sopenharmony_ci  // ===========================================================================
3471cb0ef41Sopenharmony_ci
3481cb0ef41Sopenharmony_ci  // Interface used by the gap resolver to emit moves and swaps.
3491cb0ef41Sopenharmony_ci  void AssembleMove(InstructionOperand* source,
3501cb0ef41Sopenharmony_ci                    InstructionOperand* destination) final;
3511cb0ef41Sopenharmony_ci  void AssembleSwap(InstructionOperand* source,
3521cb0ef41Sopenharmony_ci                    InstructionOperand* destination) final;
3531cb0ef41Sopenharmony_ci
3541cb0ef41Sopenharmony_ci  // ===========================================================================
3551cb0ef41Sopenharmony_ci  // =================== Jump table construction methods. ======================
3561cb0ef41Sopenharmony_ci  // ===========================================================================
3571cb0ef41Sopenharmony_ci
3581cb0ef41Sopenharmony_ci  class JumpTable;
3591cb0ef41Sopenharmony_ci  // Adds a jump table that is emitted after the actual code.  Returns label
3601cb0ef41Sopenharmony_ci  // pointing to the beginning of the table.  {targets} is assumed to be static
3611cb0ef41Sopenharmony_ci  // or zone allocated.
3621cb0ef41Sopenharmony_ci  Label* AddJumpTable(Label** targets, size_t target_count);
3631cb0ef41Sopenharmony_ci  // Emits a jump table.
3641cb0ef41Sopenharmony_ci  void AssembleJumpTable(Label** targets, size_t target_count);
3651cb0ef41Sopenharmony_ci
3661cb0ef41Sopenharmony_ci  // ===========================================================================
3671cb0ef41Sopenharmony_ci  // ================== Deoptimization table construction. =====================
3681cb0ef41Sopenharmony_ci  // ===========================================================================
3691cb0ef41Sopenharmony_ci
3701cb0ef41Sopenharmony_ci  void RecordCallPosition(Instruction* instr);
3711cb0ef41Sopenharmony_ci  Handle<DeoptimizationData> GenerateDeoptimizationData();
3721cb0ef41Sopenharmony_ci  int DefineDeoptimizationLiteral(DeoptimizationLiteral literal);
3731cb0ef41Sopenharmony_ci  DeoptimizationEntry const& GetDeoptimizationEntry(Instruction* instr,
3741cb0ef41Sopenharmony_ci                                                    size_t frame_state_offset);
3751cb0ef41Sopenharmony_ci  DeoptimizationExit* BuildTranslation(Instruction* instr, int pc_offset,
3761cb0ef41Sopenharmony_ci                                       size_t frame_state_offset,
3771cb0ef41Sopenharmony_ci                                       size_t immediate_args_count,
3781cb0ef41Sopenharmony_ci                                       OutputFrameStateCombine state_combine);
3791cb0ef41Sopenharmony_ci  void BuildTranslationForFrameStateDescriptor(
3801cb0ef41Sopenharmony_ci      FrameStateDescriptor* descriptor, InstructionOperandIterator* iter,
3811cb0ef41Sopenharmony_ci      OutputFrameStateCombine state_combine);
3821cb0ef41Sopenharmony_ci  void TranslateStateValueDescriptor(StateValueDescriptor* desc,
3831cb0ef41Sopenharmony_ci                                     StateValueList* nested,
3841cb0ef41Sopenharmony_ci                                     InstructionOperandIterator* iter);
3851cb0ef41Sopenharmony_ci  void TranslateFrameStateDescriptorOperands(FrameStateDescriptor* desc,
3861cb0ef41Sopenharmony_ci                                             InstructionOperandIterator* iter);
3871cb0ef41Sopenharmony_ci  void AddTranslationForOperand(Instruction* instr, InstructionOperand* op,
3881cb0ef41Sopenharmony_ci                                MachineType type);
3891cb0ef41Sopenharmony_ci  void MarkLazyDeoptSite();
3901cb0ef41Sopenharmony_ci
3911cb0ef41Sopenharmony_ci  void PrepareForDeoptimizationExits(ZoneDeque<DeoptimizationExit*>* exits);
3921cb0ef41Sopenharmony_ci  DeoptimizationExit* AddDeoptimizationExit(Instruction* instr,
3931cb0ef41Sopenharmony_ci                                            size_t frame_state_offset,
3941cb0ef41Sopenharmony_ci                                            size_t immediate_args_count);
3951cb0ef41Sopenharmony_ci
3961cb0ef41Sopenharmony_ci  // ===========================================================================
3971cb0ef41Sopenharmony_ci
3981cb0ef41Sopenharmony_ci  struct HandlerInfo {
3991cb0ef41Sopenharmony_ci    Label* handler;
4001cb0ef41Sopenharmony_ci    int pc_offset;
4011cb0ef41Sopenharmony_ci  };
4021cb0ef41Sopenharmony_ci
4031cb0ef41Sopenharmony_ci  friend class OutOfLineCode;
4041cb0ef41Sopenharmony_ci  friend class CodeGeneratorTester;
4051cb0ef41Sopenharmony_ci
4061cb0ef41Sopenharmony_ci  Zone* zone_;
4071cb0ef41Sopenharmony_ci  Isolate* isolate_;
4081cb0ef41Sopenharmony_ci  FrameAccessState* frame_access_state_;
4091cb0ef41Sopenharmony_ci  Linkage* const linkage_;
4101cb0ef41Sopenharmony_ci  InstructionSequence* const instructions_;
4111cb0ef41Sopenharmony_ci  UnwindingInfoWriter unwinding_info_writer_;
4121cb0ef41Sopenharmony_ci  OptimizedCompilationInfo* const info_;
4131cb0ef41Sopenharmony_ci  Label* const labels_;
4141cb0ef41Sopenharmony_ci  Label return_label_;
4151cb0ef41Sopenharmony_ci  RpoNumber current_block_;
4161cb0ef41Sopenharmony_ci  SourcePosition start_source_position_;
4171cb0ef41Sopenharmony_ci  SourcePosition current_source_position_;
4181cb0ef41Sopenharmony_ci  TurboAssembler tasm_;
4191cb0ef41Sopenharmony_ci  GapResolver resolver_;
4201cb0ef41Sopenharmony_ci  SafepointTableBuilder safepoints_;
4211cb0ef41Sopenharmony_ci  ZoneVector<HandlerInfo> handlers_;
4221cb0ef41Sopenharmony_ci  int next_deoptimization_id_ = 0;
4231cb0ef41Sopenharmony_ci  int deopt_exit_start_offset_ = 0;
4241cb0ef41Sopenharmony_ci  int eager_deopt_count_ = 0;
4251cb0ef41Sopenharmony_ci  int lazy_deopt_count_ = 0;
4261cb0ef41Sopenharmony_ci  ZoneDeque<DeoptimizationExit*> deoptimization_exits_;
4271cb0ef41Sopenharmony_ci  ZoneDeque<DeoptimizationLiteral> deoptimization_literals_;
4281cb0ef41Sopenharmony_ci  size_t inlined_function_count_ = 0;
4291cb0ef41Sopenharmony_ci  TranslationArrayBuilder translations_;
4301cb0ef41Sopenharmony_ci  int handler_table_offset_ = 0;
4311cb0ef41Sopenharmony_ci  int last_lazy_deopt_pc_ = 0;
4321cb0ef41Sopenharmony_ci
4331cb0ef41Sopenharmony_ci  // Deoptimization exits must be as small as possible, since their count grows
4341cb0ef41Sopenharmony_ci  // with function size. {jump_deoptimization_entry_labels_} is an optimization
4351cb0ef41Sopenharmony_ci  // to that effect, which extracts the (potentially large) instruction
4361cb0ef41Sopenharmony_ci  // sequence for the final jump to the deoptimization entry into a single spot
4371cb0ef41Sopenharmony_ci  // per Code object. All deopt exits can then near-call to this label. Note:
4381cb0ef41Sopenharmony_ci  // not used on all architectures.
4391cb0ef41Sopenharmony_ci  Label jump_deoptimization_entry_labels_[kDeoptimizeKindCount];
4401cb0ef41Sopenharmony_ci
4411cb0ef41Sopenharmony_ci  // The maximal combined height of all frames produced upon deoptimization, and
4421cb0ef41Sopenharmony_ci  // the maximal number of pushed arguments for function calls. Applied as an
4431cb0ef41Sopenharmony_ci  // offset to the first stack check of an optimized function.
4441cb0ef41Sopenharmony_ci  const size_t max_unoptimized_frame_height_;
4451cb0ef41Sopenharmony_ci  const size_t max_pushed_argument_count_;
4461cb0ef41Sopenharmony_ci
4471cb0ef41Sopenharmony_ci  // kArchCallCFunction could be reached either:
4481cb0ef41Sopenharmony_ci  //   kArchCallCFunction;
4491cb0ef41Sopenharmony_ci  // or:
4501cb0ef41Sopenharmony_ci  //   kArchSaveCallerRegisters;
4511cb0ef41Sopenharmony_ci  //   kArchCallCFunction;
4521cb0ef41Sopenharmony_ci  //   kArchRestoreCallerRegisters;
4531cb0ef41Sopenharmony_ci  // The boolean is used to distinguish the two cases. In the latter case, we
4541cb0ef41Sopenharmony_ci  // also need to decide if FP registers need to be saved, which is controlled
4551cb0ef41Sopenharmony_ci  // by fp_mode_.
4561cb0ef41Sopenharmony_ci  bool caller_registers_saved_;
4571cb0ef41Sopenharmony_ci  SaveFPRegsMode fp_mode_;
4581cb0ef41Sopenharmony_ci
4591cb0ef41Sopenharmony_ci  JumpTable* jump_tables_;
4601cb0ef41Sopenharmony_ci  OutOfLineCode* ools_;
4611cb0ef41Sopenharmony_ci  base::Optional<OsrHelper> osr_helper_;
4621cb0ef41Sopenharmony_ci  int osr_pc_offset_;
4631cb0ef41Sopenharmony_ci  int optimized_out_literal_id_;
4641cb0ef41Sopenharmony_ci  SourcePositionTableBuilder source_position_table_builder_;
4651cb0ef41Sopenharmony_ci  ZoneVector<trap_handler::ProtectedInstructionData> protected_instructions_;
4661cb0ef41Sopenharmony_ci  CodeGenResult result_;
4671cb0ef41Sopenharmony_ci  ZoneVector<int> block_starts_;
4681cb0ef41Sopenharmony_ci  TurbolizerCodeOffsetsInfo offsets_info_;
4691cb0ef41Sopenharmony_ci  ZoneVector<TurbolizerInstructionStartInfo> instr_starts_;
4701cb0ef41Sopenharmony_ci
4711cb0ef41Sopenharmony_ci  const char* debug_name_ = nullptr;
4721cb0ef41Sopenharmony_ci};
4731cb0ef41Sopenharmony_ci
4741cb0ef41Sopenharmony_ci}  // namespace compiler
4751cb0ef41Sopenharmony_ci}  // namespace internal
4761cb0ef41Sopenharmony_ci}  // namespace v8
4771cb0ef41Sopenharmony_ci
4781cb0ef41Sopenharmony_ci#endif  // V8_COMPILER_BACKEND_CODE_GENERATOR_H_
479