11cb0ef41Sopenharmony_ci// Copyright 2012 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_CODEGEN_REGISTER_BASE_H_
61cb0ef41Sopenharmony_ci#define V8_CODEGEN_REGISTER_BASE_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include "src/base/bits.h"
91cb0ef41Sopenharmony_ci#include "src/base/bounds.h"
101cb0ef41Sopenharmony_ci#include "src/common/globals.h"
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_cinamespace v8 {
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_cinamespace internal {
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci// Base type for CPU Registers.
171cb0ef41Sopenharmony_ci//
181cb0ef41Sopenharmony_ci// 1) We would prefer to use an enum for registers, but enum values are
191cb0ef41Sopenharmony_ci// assignment-compatible with int, which has caused code-generation bugs.
201cb0ef41Sopenharmony_ci//
211cb0ef41Sopenharmony_ci// 2) By not using an enum, we are possibly preventing the compiler from
221cb0ef41Sopenharmony_ci// doing certain constant folds, which may significantly reduce the
231cb0ef41Sopenharmony_ci// code generated for some assembly instructions (because they boil down
241cb0ef41Sopenharmony_ci// to a few constants). If this is a problem, we could change the code
251cb0ef41Sopenharmony_ci// such that we use an enum in optimized mode, and the class in debug
261cb0ef41Sopenharmony_ci// mode. This way we get the compile-time error checking in debug mode
271cb0ef41Sopenharmony_ci// and best performance in optimized code.
281cb0ef41Sopenharmony_citemplate <typename SubType, int kAfterLastRegister>
291cb0ef41Sopenharmony_ciclass RegisterBase {
301cb0ef41Sopenharmony_ci public:
311cb0ef41Sopenharmony_ci  static constexpr int8_t kCode_no_reg = -1;
321cb0ef41Sopenharmony_ci  static constexpr int8_t kNumRegisters = kAfterLastRegister;
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci  static constexpr SubType no_reg() { return SubType{kCode_no_reg}; }
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ci  static constexpr SubType from_code(int8_t code) {
371cb0ef41Sopenharmony_ci    DCHECK(base::IsInRange(static_cast<int>(code), 0, kNumRegisters - 1));
381cb0ef41Sopenharmony_ci    return SubType{code};
391cb0ef41Sopenharmony_ci  }
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci  constexpr bool is_valid() const { return reg_code_ != kCode_no_reg; }
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci  constexpr int8_t code() const {
441cb0ef41Sopenharmony_ci    DCHECK(is_valid());
451cb0ef41Sopenharmony_ci    return reg_code_;
461cb0ef41Sopenharmony_ci  }
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci  inline constexpr bool operator==(SubType other) const {
491cb0ef41Sopenharmony_ci    return reg_code_ == other.reg_code_;
501cb0ef41Sopenharmony_ci  }
511cb0ef41Sopenharmony_ci  inline constexpr bool operator!=(SubType other) const {
521cb0ef41Sopenharmony_ci    return reg_code_ != other.reg_code_;
531cb0ef41Sopenharmony_ci  }
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci  // Used to print the name of some special registers.
561cb0ef41Sopenharmony_ci  static const char* GetSpecialRegisterName(int code) { return "UNKNOWN"; }
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci protected:
591cb0ef41Sopenharmony_ci  explicit constexpr RegisterBase(int code) : reg_code_(code) {}
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci private:
621cb0ef41Sopenharmony_ci  int8_t reg_code_;
631cb0ef41Sopenharmony_ci  STATIC_ASSERT(kAfterLastRegister <= kMaxInt8);
641cb0ef41Sopenharmony_ci};
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_citemplate <typename RegType,
671cb0ef41Sopenharmony_ci          typename = decltype(RegisterName(std::declval<RegType>()))>
681cb0ef41Sopenharmony_ciinline std::ostream& operator<<(std::ostream& os, RegType reg) {
691cb0ef41Sopenharmony_ci  return os << RegisterName(reg);
701cb0ef41Sopenharmony_ci}
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci// Helper macros to define a {RegisterName} method based on a macro list
731cb0ef41Sopenharmony_ci// containing all names.
741cb0ef41Sopenharmony_ci#define DEFINE_REGISTER_NAMES_NAME(name) #name,
751cb0ef41Sopenharmony_ci#define DEFINE_REGISTER_NAMES(RegType, LIST)                                   \
761cb0ef41Sopenharmony_ci  inline const char* RegisterName(RegType reg) {                               \
771cb0ef41Sopenharmony_ci    static constexpr const char* Names[] = {LIST(DEFINE_REGISTER_NAMES_NAME)}; \
781cb0ef41Sopenharmony_ci    STATIC_ASSERT(arraysize(Names) == RegType::kNumRegisters);                 \
791cb0ef41Sopenharmony_ci    return reg.is_valid() ? Names[reg.code()] : "invalid";                     \
801cb0ef41Sopenharmony_ci  }
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci}  // namespace internal
831cb0ef41Sopenharmony_ci}  // namespace v8
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci#endif  // V8_CODEGEN_REGISTER_BASE_H_
86