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_INSTRUCTION_SELECTOR_IMPL_H_
61cb0ef41Sopenharmony_ci#define V8_COMPILER_BACKEND_INSTRUCTION_SELECTOR_IMPL_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include "src/codegen/macro-assembler.h"
91cb0ef41Sopenharmony_ci#include "src/compiler/backend/instruction-selector.h"
101cb0ef41Sopenharmony_ci#include "src/compiler/backend/instruction.h"
111cb0ef41Sopenharmony_ci#include "src/compiler/common-operator.h"
121cb0ef41Sopenharmony_ci#include "src/compiler/linkage.h"
131cb0ef41Sopenharmony_ci#include "src/compiler/schedule.h"
141cb0ef41Sopenharmony_ci#include "src/objects/tagged-index.h"
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_cinamespace v8 {
171cb0ef41Sopenharmony_cinamespace internal {
181cb0ef41Sopenharmony_cinamespace compiler {
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_cistruct CaseInfo {
211cb0ef41Sopenharmony_ci  int32_t value;  // The case value.
221cb0ef41Sopenharmony_ci  int32_t order;  // The order for lowering to comparisons (less means earlier).
231cb0ef41Sopenharmony_ci  BasicBlock* branch;  // The basic blocks corresponding to the case value.
241cb0ef41Sopenharmony_ci};
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ciinline bool operator<(const CaseInfo& l, const CaseInfo& r) {
271cb0ef41Sopenharmony_ci  return l.order < r.order;
281cb0ef41Sopenharmony_ci}
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci// Helper struct containing data about a table or lookup switch.
311cb0ef41Sopenharmony_ciclass SwitchInfo {
321cb0ef41Sopenharmony_ci public:
331cb0ef41Sopenharmony_ci  SwitchInfo(ZoneVector<CaseInfo> const& cases, int32_t min_value,
341cb0ef41Sopenharmony_ci             int32_t max_value, BasicBlock* default_branch)
351cb0ef41Sopenharmony_ci      : cases_(cases),
361cb0ef41Sopenharmony_ci        min_value_(min_value),
371cb0ef41Sopenharmony_ci        max_value_(max_value),
381cb0ef41Sopenharmony_ci        default_branch_(default_branch) {
391cb0ef41Sopenharmony_ci    if (cases.size() != 0) {
401cb0ef41Sopenharmony_ci      DCHECK_LE(min_value, max_value);
411cb0ef41Sopenharmony_ci      // Note that {value_range} can be 0 if {min_value} is -2^31 and
421cb0ef41Sopenharmony_ci      // {max_value} is 2^31-1, so don't assume that it's non-zero below.
431cb0ef41Sopenharmony_ci      value_range_ =
441cb0ef41Sopenharmony_ci          1u + bit_cast<uint32_t>(max_value) - bit_cast<uint32_t>(min_value);
451cb0ef41Sopenharmony_ci    } else {
461cb0ef41Sopenharmony_ci      value_range_ = 0;
471cb0ef41Sopenharmony_ci    }
481cb0ef41Sopenharmony_ci  }
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci  std::vector<CaseInfo> CasesSortedByValue() const {
511cb0ef41Sopenharmony_ci    std::vector<CaseInfo> result(cases_.begin(), cases_.end());
521cb0ef41Sopenharmony_ci    std::stable_sort(result.begin(), result.end(),
531cb0ef41Sopenharmony_ci                     [](CaseInfo a, CaseInfo b) { return a.value < b.value; });
541cb0ef41Sopenharmony_ci    return result;
551cb0ef41Sopenharmony_ci  }
561cb0ef41Sopenharmony_ci  const ZoneVector<CaseInfo>& CasesUnsorted() const { return cases_; }
571cb0ef41Sopenharmony_ci  int32_t min_value() const { return min_value_; }
581cb0ef41Sopenharmony_ci  int32_t max_value() const { return max_value_; }
591cb0ef41Sopenharmony_ci  size_t value_range() const { return value_range_; }
601cb0ef41Sopenharmony_ci  size_t case_count() const { return cases_.size(); }
611cb0ef41Sopenharmony_ci  BasicBlock* default_branch() const { return default_branch_; }
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci private:
641cb0ef41Sopenharmony_ci  const ZoneVector<CaseInfo>& cases_;
651cb0ef41Sopenharmony_ci  int32_t min_value_;   // minimum value of {cases_}
661cb0ef41Sopenharmony_ci  int32_t max_value_;   // maximum value of {cases_}
671cb0ef41Sopenharmony_ci  size_t value_range_;  // |max_value - min_value| + 1
681cb0ef41Sopenharmony_ci  BasicBlock* default_branch_;
691cb0ef41Sopenharmony_ci};
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci// A helper class for the instruction selector that simplifies construction of
721cb0ef41Sopenharmony_ci// Operands. This class implements a base for architecture-specific helpers.
731cb0ef41Sopenharmony_ciclass OperandGenerator {
741cb0ef41Sopenharmony_ci public:
751cb0ef41Sopenharmony_ci  explicit OperandGenerator(InstructionSelector* selector)
761cb0ef41Sopenharmony_ci      : selector_(selector) {}
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci  InstructionOperand NoOutput() {
791cb0ef41Sopenharmony_ci    return InstructionOperand();  // Generates an invalid operand.
801cb0ef41Sopenharmony_ci  }
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci  InstructionOperand DefineAsRegister(Node* node) {
831cb0ef41Sopenharmony_ci    return Define(node,
841cb0ef41Sopenharmony_ci                  UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
851cb0ef41Sopenharmony_ci                                     GetVReg(node)));
861cb0ef41Sopenharmony_ci  }
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci  InstructionOperand DefineSameAsInput(Node* node, int input_index) {
891cb0ef41Sopenharmony_ci    return Define(node, UnallocatedOperand(GetVReg(node), input_index));
901cb0ef41Sopenharmony_ci  }
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci  InstructionOperand DefineSameAsFirst(Node* node) {
931cb0ef41Sopenharmony_ci    return DefineSameAsInput(node, 0);
941cb0ef41Sopenharmony_ci  }
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci  InstructionOperand DefineAsFixed(Node* node, Register reg) {
971cb0ef41Sopenharmony_ci    return Define(node, UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
981cb0ef41Sopenharmony_ci                                           reg.code(), GetVReg(node)));
991cb0ef41Sopenharmony_ci  }
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci  template <typename FPRegType>
1021cb0ef41Sopenharmony_ci  InstructionOperand DefineAsFixed(Node* node, FPRegType reg) {
1031cb0ef41Sopenharmony_ci    return Define(node,
1041cb0ef41Sopenharmony_ci                  UnallocatedOperand(UnallocatedOperand::FIXED_FP_REGISTER,
1051cb0ef41Sopenharmony_ci                                     reg.code(), GetVReg(node)));
1061cb0ef41Sopenharmony_ci  }
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci  InstructionOperand DefineAsConstant(Node* node) {
1091cb0ef41Sopenharmony_ci    selector()->MarkAsDefined(node);
1101cb0ef41Sopenharmony_ci    int virtual_register = GetVReg(node);
1111cb0ef41Sopenharmony_ci    sequence()->AddConstant(virtual_register, ToConstant(node));
1121cb0ef41Sopenharmony_ci    return ConstantOperand(virtual_register);
1131cb0ef41Sopenharmony_ci  }
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci  InstructionOperand DefineAsLocation(Node* node, LinkageLocation location) {
1161cb0ef41Sopenharmony_ci    return Define(node, ToUnallocatedOperand(location, GetVReg(node)));
1171cb0ef41Sopenharmony_ci  }
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci  InstructionOperand DefineAsDualLocation(Node* node,
1201cb0ef41Sopenharmony_ci                                          LinkageLocation primary_location,
1211cb0ef41Sopenharmony_ci                                          LinkageLocation secondary_location) {
1221cb0ef41Sopenharmony_ci    return Define(node,
1231cb0ef41Sopenharmony_ci                  ToDualLocationUnallocatedOperand(
1241cb0ef41Sopenharmony_ci                      primary_location, secondary_location, GetVReg(node)));
1251cb0ef41Sopenharmony_ci  }
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  InstructionOperand Use(Node* node) {
1281cb0ef41Sopenharmony_ci    return Use(node, UnallocatedOperand(UnallocatedOperand::NONE,
1291cb0ef41Sopenharmony_ci                                        UnallocatedOperand::USED_AT_START,
1301cb0ef41Sopenharmony_ci                                        GetVReg(node)));
1311cb0ef41Sopenharmony_ci  }
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci  InstructionOperand UseAnyAtEnd(Node* node) {
1341cb0ef41Sopenharmony_ci    return Use(node, UnallocatedOperand(UnallocatedOperand::REGISTER_OR_SLOT,
1351cb0ef41Sopenharmony_ci                                        UnallocatedOperand::USED_AT_END,
1361cb0ef41Sopenharmony_ci                                        GetVReg(node)));
1371cb0ef41Sopenharmony_ci  }
1381cb0ef41Sopenharmony_ci
1391cb0ef41Sopenharmony_ci  InstructionOperand UseAny(Node* node) {
1401cb0ef41Sopenharmony_ci    return Use(node, UnallocatedOperand(UnallocatedOperand::REGISTER_OR_SLOT,
1411cb0ef41Sopenharmony_ci                                        UnallocatedOperand::USED_AT_START,
1421cb0ef41Sopenharmony_ci                                        GetVReg(node)));
1431cb0ef41Sopenharmony_ci  }
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ci  InstructionOperand UseRegisterOrSlotOrConstant(Node* node) {
1461cb0ef41Sopenharmony_ci    return Use(node, UnallocatedOperand(
1471cb0ef41Sopenharmony_ci                         UnallocatedOperand::REGISTER_OR_SLOT_OR_CONSTANT,
1481cb0ef41Sopenharmony_ci                         UnallocatedOperand::USED_AT_START, GetVReg(node)));
1491cb0ef41Sopenharmony_ci  }
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci  InstructionOperand UseUniqueRegisterOrSlotOrConstant(Node* node) {
1521cb0ef41Sopenharmony_ci    return Use(node, UnallocatedOperand(
1531cb0ef41Sopenharmony_ci                         UnallocatedOperand::REGISTER_OR_SLOT_OR_CONSTANT,
1541cb0ef41Sopenharmony_ci                         GetVReg(node)));
1551cb0ef41Sopenharmony_ci  }
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci  InstructionOperand UseRegister(Node* node) {
1581cb0ef41Sopenharmony_ci    return Use(node, UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
1591cb0ef41Sopenharmony_ci                                        UnallocatedOperand::USED_AT_START,
1601cb0ef41Sopenharmony_ci                                        GetVReg(node)));
1611cb0ef41Sopenharmony_ci  }
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_ci  InstructionOperand UseUniqueSlot(Node* node) {
1641cb0ef41Sopenharmony_ci    return Use(node, UnallocatedOperand(UnallocatedOperand::MUST_HAVE_SLOT,
1651cb0ef41Sopenharmony_ci                                        GetVReg(node)));
1661cb0ef41Sopenharmony_ci  }
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_ci  // Use register or operand for the node. If a register is chosen, it won't
1691cb0ef41Sopenharmony_ci  // alias any temporary or output registers.
1701cb0ef41Sopenharmony_ci  InstructionOperand UseUnique(Node* node) {
1711cb0ef41Sopenharmony_ci    return Use(node,
1721cb0ef41Sopenharmony_ci               UnallocatedOperand(UnallocatedOperand::NONE, GetVReg(node)));
1731cb0ef41Sopenharmony_ci  }
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci  // Use a unique register for the node that does not alias any temporary or
1761cb0ef41Sopenharmony_ci  // output registers.
1771cb0ef41Sopenharmony_ci  InstructionOperand UseUniqueRegister(Node* node) {
1781cb0ef41Sopenharmony_ci    return Use(node, UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
1791cb0ef41Sopenharmony_ci                                        GetVReg(node)));
1801cb0ef41Sopenharmony_ci  }
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ci  enum class RegisterUseKind { kUseRegister, kUseUniqueRegister };
1831cb0ef41Sopenharmony_ci  InstructionOperand UseRegister(Node* node, RegisterUseKind unique_reg) {
1841cb0ef41Sopenharmony_ci    if (V8_LIKELY(unique_reg == RegisterUseKind::kUseRegister)) {
1851cb0ef41Sopenharmony_ci      return UseRegister(node);
1861cb0ef41Sopenharmony_ci    } else {
1871cb0ef41Sopenharmony_ci      DCHECK_EQ(unique_reg, RegisterUseKind::kUseUniqueRegister);
1881cb0ef41Sopenharmony_ci      return UseUniqueRegister(node);
1891cb0ef41Sopenharmony_ci    }
1901cb0ef41Sopenharmony_ci  }
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ci  InstructionOperand UseFixed(Node* node, Register reg) {
1931cb0ef41Sopenharmony_ci    return Use(node, UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
1941cb0ef41Sopenharmony_ci                                        reg.code(), GetVReg(node)));
1951cb0ef41Sopenharmony_ci  }
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci  template <typename FPRegType>
1981cb0ef41Sopenharmony_ci  InstructionOperand UseFixed(Node* node, FPRegType reg) {
1991cb0ef41Sopenharmony_ci    return Use(node, UnallocatedOperand(UnallocatedOperand::FIXED_FP_REGISTER,
2001cb0ef41Sopenharmony_ci                                        reg.code(), GetVReg(node)));
2011cb0ef41Sopenharmony_ci  }
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_ci  InstructionOperand UseImmediate(int immediate) {
2041cb0ef41Sopenharmony_ci    return sequence()->AddImmediate(Constant(immediate));
2051cb0ef41Sopenharmony_ci  }
2061cb0ef41Sopenharmony_ci
2071cb0ef41Sopenharmony_ci  InstructionOperand UseImmediate64(int64_t immediate) {
2081cb0ef41Sopenharmony_ci    return sequence()->AddImmediate(Constant(immediate));
2091cb0ef41Sopenharmony_ci  }
2101cb0ef41Sopenharmony_ci
2111cb0ef41Sopenharmony_ci  InstructionOperand UseImmediate(Node* node) {
2121cb0ef41Sopenharmony_ci    return sequence()->AddImmediate(ToConstant(node));
2131cb0ef41Sopenharmony_ci  }
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_ci  InstructionOperand UseNegatedImmediate(Node* node) {
2161cb0ef41Sopenharmony_ci    return sequence()->AddImmediate(ToNegatedConstant(node));
2171cb0ef41Sopenharmony_ci  }
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ci  InstructionOperand UseLocation(Node* node, LinkageLocation location) {
2201cb0ef41Sopenharmony_ci    return Use(node, ToUnallocatedOperand(location, GetVReg(node)));
2211cb0ef41Sopenharmony_ci  }
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_ci  // Used to force gap moves from the from_location to the to_location
2241cb0ef41Sopenharmony_ci  // immediately before an instruction.
2251cb0ef41Sopenharmony_ci  InstructionOperand UsePointerLocation(LinkageLocation to_location,
2261cb0ef41Sopenharmony_ci                                        LinkageLocation from_location) {
2271cb0ef41Sopenharmony_ci    UnallocatedOperand casted_from_operand =
2281cb0ef41Sopenharmony_ci        UnallocatedOperand::cast(TempLocation(from_location));
2291cb0ef41Sopenharmony_ci    selector_->Emit(kArchNop, casted_from_operand);
2301cb0ef41Sopenharmony_ci    return ToUnallocatedOperand(to_location,
2311cb0ef41Sopenharmony_ci                                casted_from_operand.virtual_register());
2321cb0ef41Sopenharmony_ci  }
2331cb0ef41Sopenharmony_ci
2341cb0ef41Sopenharmony_ci  InstructionOperand TempRegister() {
2351cb0ef41Sopenharmony_ci    return UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
2361cb0ef41Sopenharmony_ci                              UnallocatedOperand::USED_AT_START,
2371cb0ef41Sopenharmony_ci                              sequence()->NextVirtualRegister());
2381cb0ef41Sopenharmony_ci  }
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_ci  int AllocateVirtualRegister() { return sequence()->NextVirtualRegister(); }
2411cb0ef41Sopenharmony_ci
2421cb0ef41Sopenharmony_ci  InstructionOperand DefineSameAsFirstForVreg(int vreg) {
2431cb0ef41Sopenharmony_ci    return UnallocatedOperand(UnallocatedOperand::SAME_AS_INPUT, vreg);
2441cb0ef41Sopenharmony_ci  }
2451cb0ef41Sopenharmony_ci
2461cb0ef41Sopenharmony_ci  InstructionOperand DefineAsRegistertForVreg(int vreg) {
2471cb0ef41Sopenharmony_ci    return UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER, vreg);
2481cb0ef41Sopenharmony_ci  }
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_ci  InstructionOperand UseRegisterForVreg(int vreg) {
2511cb0ef41Sopenharmony_ci    return UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
2521cb0ef41Sopenharmony_ci                              UnallocatedOperand::USED_AT_START, vreg);
2531cb0ef41Sopenharmony_ci  }
2541cb0ef41Sopenharmony_ci
2551cb0ef41Sopenharmony_ci  // The kind of register generated for memory operands. kRegister is alive
2561cb0ef41Sopenharmony_ci  // until the start of the operation, kUniqueRegister until the end.
2571cb0ef41Sopenharmony_ci  enum RegisterMode {
2581cb0ef41Sopenharmony_ci    kRegister,
2591cb0ef41Sopenharmony_ci    kUniqueRegister,
2601cb0ef41Sopenharmony_ci  };
2611cb0ef41Sopenharmony_ci
2621cb0ef41Sopenharmony_ci  InstructionOperand UseRegisterWithMode(Node* node,
2631cb0ef41Sopenharmony_ci                                         RegisterMode register_mode) {
2641cb0ef41Sopenharmony_ci    return register_mode == kRegister ? UseRegister(node)
2651cb0ef41Sopenharmony_ci                                      : UseUniqueRegister(node);
2661cb0ef41Sopenharmony_ci  }
2671cb0ef41Sopenharmony_ci
2681cb0ef41Sopenharmony_ci  InstructionOperand TempDoubleRegister() {
2691cb0ef41Sopenharmony_ci    UnallocatedOperand op = UnallocatedOperand(
2701cb0ef41Sopenharmony_ci        UnallocatedOperand::MUST_HAVE_REGISTER,
2711cb0ef41Sopenharmony_ci        UnallocatedOperand::USED_AT_START, sequence()->NextVirtualRegister());
2721cb0ef41Sopenharmony_ci    sequence()->MarkAsRepresentation(MachineRepresentation::kFloat64,
2731cb0ef41Sopenharmony_ci                                     op.virtual_register());
2741cb0ef41Sopenharmony_ci    return op;
2751cb0ef41Sopenharmony_ci  }
2761cb0ef41Sopenharmony_ci
2771cb0ef41Sopenharmony_ci  InstructionOperand TempSimd128Register() {
2781cb0ef41Sopenharmony_ci    UnallocatedOperand op = UnallocatedOperand(
2791cb0ef41Sopenharmony_ci        UnallocatedOperand::MUST_HAVE_REGISTER,
2801cb0ef41Sopenharmony_ci        UnallocatedOperand::USED_AT_START, sequence()->NextVirtualRegister());
2811cb0ef41Sopenharmony_ci    sequence()->MarkAsRepresentation(MachineRepresentation::kSimd128,
2821cb0ef41Sopenharmony_ci                                     op.virtual_register());
2831cb0ef41Sopenharmony_ci    return op;
2841cb0ef41Sopenharmony_ci  }
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_ci  InstructionOperand TempRegister(Register reg) {
2871cb0ef41Sopenharmony_ci    return UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER, reg.code(),
2881cb0ef41Sopenharmony_ci                              InstructionOperand::kInvalidVirtualRegister);
2891cb0ef41Sopenharmony_ci  }
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_ci  template <typename FPRegType>
2921cb0ef41Sopenharmony_ci  InstructionOperand TempFpRegister(FPRegType reg) {
2931cb0ef41Sopenharmony_ci    UnallocatedOperand op =
2941cb0ef41Sopenharmony_ci        UnallocatedOperand(UnallocatedOperand::FIXED_FP_REGISTER, reg.code(),
2951cb0ef41Sopenharmony_ci                           sequence()->NextVirtualRegister());
2961cb0ef41Sopenharmony_ci    sequence()->MarkAsRepresentation(MachineRepresentation::kSimd128,
2971cb0ef41Sopenharmony_ci                                     op.virtual_register());
2981cb0ef41Sopenharmony_ci    return op;
2991cb0ef41Sopenharmony_ci  }
3001cb0ef41Sopenharmony_ci
3011cb0ef41Sopenharmony_ci  InstructionOperand TempImmediate(int32_t imm) {
3021cb0ef41Sopenharmony_ci    return sequence()->AddImmediate(Constant(imm));
3031cb0ef41Sopenharmony_ci  }
3041cb0ef41Sopenharmony_ci
3051cb0ef41Sopenharmony_ci  InstructionOperand TempLocation(LinkageLocation location) {
3061cb0ef41Sopenharmony_ci    return ToUnallocatedOperand(location, sequence()->NextVirtualRegister());
3071cb0ef41Sopenharmony_ci  }
3081cb0ef41Sopenharmony_ci
3091cb0ef41Sopenharmony_ci  InstructionOperand Label(BasicBlock* block) {
3101cb0ef41Sopenharmony_ci    return sequence()->AddImmediate(
3111cb0ef41Sopenharmony_ci        Constant(RpoNumber::FromInt(block->rpo_number())));
3121cb0ef41Sopenharmony_ci  }
3131cb0ef41Sopenharmony_ci
3141cb0ef41Sopenharmony_ci protected:
3151cb0ef41Sopenharmony_ci  InstructionSelector* selector() const { return selector_; }
3161cb0ef41Sopenharmony_ci  InstructionSequence* sequence() const { return selector()->sequence(); }
3171cb0ef41Sopenharmony_ci  Zone* zone() const { return selector()->instruction_zone(); }
3181cb0ef41Sopenharmony_ci
3191cb0ef41Sopenharmony_ci private:
3201cb0ef41Sopenharmony_ci  int GetVReg(Node* node) const { return selector_->GetVirtualRegister(node); }
3211cb0ef41Sopenharmony_ci
3221cb0ef41Sopenharmony_ci  static Constant ToConstant(const Node* node) {
3231cb0ef41Sopenharmony_ci    switch (node->opcode()) {
3241cb0ef41Sopenharmony_ci      case IrOpcode::kInt32Constant:
3251cb0ef41Sopenharmony_ci        return Constant(OpParameter<int32_t>(node->op()));
3261cb0ef41Sopenharmony_ci      case IrOpcode::kInt64Constant:
3271cb0ef41Sopenharmony_ci        return Constant(OpParameter<int64_t>(node->op()));
3281cb0ef41Sopenharmony_ci      case IrOpcode::kTaggedIndexConstant: {
3291cb0ef41Sopenharmony_ci        // Unencoded index value.
3301cb0ef41Sopenharmony_ci        intptr_t value =
3311cb0ef41Sopenharmony_ci            static_cast<intptr_t>(OpParameter<int32_t>(node->op()));
3321cb0ef41Sopenharmony_ci        DCHECK(TaggedIndex::IsValid(value));
3331cb0ef41Sopenharmony_ci        // Generate it as 32/64-bit constant in a tagged form.
3341cb0ef41Sopenharmony_ci        Address tagged_index = TaggedIndex::FromIntptr(value).ptr();
3351cb0ef41Sopenharmony_ci        if (kSystemPointerSize == kInt32Size) {
3361cb0ef41Sopenharmony_ci          return Constant(static_cast<int32_t>(tagged_index));
3371cb0ef41Sopenharmony_ci        } else {
3381cb0ef41Sopenharmony_ci          return Constant(static_cast<int64_t>(tagged_index));
3391cb0ef41Sopenharmony_ci        }
3401cb0ef41Sopenharmony_ci      }
3411cb0ef41Sopenharmony_ci      case IrOpcode::kFloat32Constant:
3421cb0ef41Sopenharmony_ci        return Constant(OpParameter<float>(node->op()));
3431cb0ef41Sopenharmony_ci      case IrOpcode::kRelocatableInt32Constant:
3441cb0ef41Sopenharmony_ci      case IrOpcode::kRelocatableInt64Constant:
3451cb0ef41Sopenharmony_ci        return Constant(OpParameter<RelocatablePtrConstantInfo>(node->op()));
3461cb0ef41Sopenharmony_ci      case IrOpcode::kFloat64Constant:
3471cb0ef41Sopenharmony_ci      case IrOpcode::kNumberConstant:
3481cb0ef41Sopenharmony_ci        return Constant(OpParameter<double>(node->op()));
3491cb0ef41Sopenharmony_ci      case IrOpcode::kExternalConstant:
3501cb0ef41Sopenharmony_ci        return Constant(OpParameter<ExternalReference>(node->op()));
3511cb0ef41Sopenharmony_ci      case IrOpcode::kComment: {
3521cb0ef41Sopenharmony_ci        // We cannot use {intptr_t} here, since the Constant constructor would
3531cb0ef41Sopenharmony_ci        // be ambiguous on some architectures.
3541cb0ef41Sopenharmony_ci        using ptrsize_int_t =
3551cb0ef41Sopenharmony_ci            std::conditional<kSystemPointerSize == 8, int64_t, int32_t>::type;
3561cb0ef41Sopenharmony_ci        return Constant(reinterpret_cast<ptrsize_int_t>(
3571cb0ef41Sopenharmony_ci            OpParameter<const char*>(node->op())));
3581cb0ef41Sopenharmony_ci      }
3591cb0ef41Sopenharmony_ci      case IrOpcode::kHeapConstant:
3601cb0ef41Sopenharmony_ci        return Constant(HeapConstantOf(node->op()));
3611cb0ef41Sopenharmony_ci      case IrOpcode::kCompressedHeapConstant:
3621cb0ef41Sopenharmony_ci        return Constant(HeapConstantOf(node->op()), true);
3631cb0ef41Sopenharmony_ci      case IrOpcode::kDelayedStringConstant:
3641cb0ef41Sopenharmony_ci        return Constant(StringConstantBaseOf(node->op()));
3651cb0ef41Sopenharmony_ci      case IrOpcode::kDeadValue: {
3661cb0ef41Sopenharmony_ci        switch (DeadValueRepresentationOf(node->op())) {
3671cb0ef41Sopenharmony_ci          case MachineRepresentation::kBit:
3681cb0ef41Sopenharmony_ci          case MachineRepresentation::kWord32:
3691cb0ef41Sopenharmony_ci          case MachineRepresentation::kTagged:
3701cb0ef41Sopenharmony_ci          case MachineRepresentation::kTaggedSigned:
3711cb0ef41Sopenharmony_ci          case MachineRepresentation::kTaggedPointer:
3721cb0ef41Sopenharmony_ci          case MachineRepresentation::kCompressed:
3731cb0ef41Sopenharmony_ci          case MachineRepresentation::kCompressedPointer:
3741cb0ef41Sopenharmony_ci            return Constant(static_cast<int32_t>(0));
3751cb0ef41Sopenharmony_ci          case MachineRepresentation::kWord64:
3761cb0ef41Sopenharmony_ci            return Constant(static_cast<int64_t>(0));
3771cb0ef41Sopenharmony_ci          case MachineRepresentation::kFloat64:
3781cb0ef41Sopenharmony_ci            return Constant(static_cast<double>(0));
3791cb0ef41Sopenharmony_ci          case MachineRepresentation::kFloat32:
3801cb0ef41Sopenharmony_ci            return Constant(static_cast<float>(0));
3811cb0ef41Sopenharmony_ci          default:
3821cb0ef41Sopenharmony_ci            UNREACHABLE();
3831cb0ef41Sopenharmony_ci        }
3841cb0ef41Sopenharmony_ci        break;
3851cb0ef41Sopenharmony_ci      }
3861cb0ef41Sopenharmony_ci      default:
3871cb0ef41Sopenharmony_ci        break;
3881cb0ef41Sopenharmony_ci    }
3891cb0ef41Sopenharmony_ci    UNREACHABLE();
3901cb0ef41Sopenharmony_ci  }
3911cb0ef41Sopenharmony_ci
3921cb0ef41Sopenharmony_ci  static Constant ToNegatedConstant(const Node* node) {
3931cb0ef41Sopenharmony_ci    switch (node->opcode()) {
3941cb0ef41Sopenharmony_ci      case IrOpcode::kInt32Constant:
3951cb0ef41Sopenharmony_ci        return Constant(-OpParameter<int32_t>(node->op()));
3961cb0ef41Sopenharmony_ci      case IrOpcode::kInt64Constant:
3971cb0ef41Sopenharmony_ci        return Constant(-OpParameter<int64_t>(node->op()));
3981cb0ef41Sopenharmony_ci      default:
3991cb0ef41Sopenharmony_ci        break;
4001cb0ef41Sopenharmony_ci    }
4011cb0ef41Sopenharmony_ci    UNREACHABLE();
4021cb0ef41Sopenharmony_ci  }
4031cb0ef41Sopenharmony_ci
4041cb0ef41Sopenharmony_ci  UnallocatedOperand Define(Node* node, UnallocatedOperand operand) {
4051cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(node);
4061cb0ef41Sopenharmony_ci    DCHECK_EQ(operand.virtual_register(), GetVReg(node));
4071cb0ef41Sopenharmony_ci    selector()->MarkAsDefined(node);
4081cb0ef41Sopenharmony_ci    return operand;
4091cb0ef41Sopenharmony_ci  }
4101cb0ef41Sopenharmony_ci
4111cb0ef41Sopenharmony_ci  UnallocatedOperand Use(Node* node, UnallocatedOperand operand) {
4121cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(node);
4131cb0ef41Sopenharmony_ci    DCHECK_EQ(operand.virtual_register(), GetVReg(node));
4141cb0ef41Sopenharmony_ci    selector()->MarkAsUsed(node);
4151cb0ef41Sopenharmony_ci    return operand;
4161cb0ef41Sopenharmony_ci  }
4171cb0ef41Sopenharmony_ci
4181cb0ef41Sopenharmony_ci  UnallocatedOperand ToDualLocationUnallocatedOperand(
4191cb0ef41Sopenharmony_ci      LinkageLocation primary_location, LinkageLocation secondary_location,
4201cb0ef41Sopenharmony_ci      int virtual_register) {
4211cb0ef41Sopenharmony_ci    // We only support the primary location being a register and the secondary
4221cb0ef41Sopenharmony_ci    // one a slot.
4231cb0ef41Sopenharmony_ci    DCHECK(primary_location.IsRegister() &&
4241cb0ef41Sopenharmony_ci           secondary_location.IsCalleeFrameSlot());
4251cb0ef41Sopenharmony_ci    int reg_id = primary_location.AsRegister();
4261cb0ef41Sopenharmony_ci    int slot_id = secondary_location.AsCalleeFrameSlot();
4271cb0ef41Sopenharmony_ci    return UnallocatedOperand(reg_id, slot_id, virtual_register);
4281cb0ef41Sopenharmony_ci  }
4291cb0ef41Sopenharmony_ci
4301cb0ef41Sopenharmony_ci  UnallocatedOperand ToUnallocatedOperand(LinkageLocation location,
4311cb0ef41Sopenharmony_ci                                          int virtual_register) {
4321cb0ef41Sopenharmony_ci    if (location.IsAnyRegister()) {
4331cb0ef41Sopenharmony_ci      // any machine register.
4341cb0ef41Sopenharmony_ci      return UnallocatedOperand(UnallocatedOperand::MUST_HAVE_REGISTER,
4351cb0ef41Sopenharmony_ci                                virtual_register);
4361cb0ef41Sopenharmony_ci    }
4371cb0ef41Sopenharmony_ci    if (location.IsCallerFrameSlot()) {
4381cb0ef41Sopenharmony_ci      // a location on the caller frame.
4391cb0ef41Sopenharmony_ci      return UnallocatedOperand(UnallocatedOperand::FIXED_SLOT,
4401cb0ef41Sopenharmony_ci                                location.AsCallerFrameSlot(), virtual_register);
4411cb0ef41Sopenharmony_ci    }
4421cb0ef41Sopenharmony_ci    if (location.IsCalleeFrameSlot()) {
4431cb0ef41Sopenharmony_ci      // a spill location on this (callee) frame.
4441cb0ef41Sopenharmony_ci      return UnallocatedOperand(UnallocatedOperand::FIXED_SLOT,
4451cb0ef41Sopenharmony_ci                                location.AsCalleeFrameSlot(), virtual_register);
4461cb0ef41Sopenharmony_ci    }
4471cb0ef41Sopenharmony_ci    // a fixed register.
4481cb0ef41Sopenharmony_ci    if (IsFloatingPoint(location.GetType().representation())) {
4491cb0ef41Sopenharmony_ci      return UnallocatedOperand(UnallocatedOperand::FIXED_FP_REGISTER,
4501cb0ef41Sopenharmony_ci                                location.AsRegister(), virtual_register);
4511cb0ef41Sopenharmony_ci    }
4521cb0ef41Sopenharmony_ci    return UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
4531cb0ef41Sopenharmony_ci                              location.AsRegister(), virtual_register);
4541cb0ef41Sopenharmony_ci  }
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ci  InstructionSelector* selector_;
4571cb0ef41Sopenharmony_ci};
4581cb0ef41Sopenharmony_ci
4591cb0ef41Sopenharmony_ci}  // namespace compiler
4601cb0ef41Sopenharmony_ci}  // namespace internal
4611cb0ef41Sopenharmony_ci}  // namespace v8
4621cb0ef41Sopenharmony_ci
4631cb0ef41Sopenharmony_ci#endif  // V8_COMPILER_BACKEND_INSTRUCTION_SELECTOR_IMPL_H_
464