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