1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_CODEGEN_REGISTER_BASE_H_ 6 #define V8_CODEGEN_REGISTER_BASE_H_ 7 8 #include "src/base/bits.h" 9 #include "src/base/bounds.h" 10 #include "src/common/globals.h" 11 12 namespace v8 { 13 14 namespace internal { 15 16 // Base type for CPU Registers. 17 // 18 // 1) We would prefer to use an enum for registers, but enum values are 19 // assignment-compatible with int, which has caused code-generation bugs. 20 // 21 // 2) By not using an enum, we are possibly preventing the compiler from 22 // doing certain constant folds, which may significantly reduce the 23 // code generated for some assembly instructions (because they boil down 24 // to a few constants). If this is a problem, we could change the code 25 // such that we use an enum in optimized mode, and the class in debug 26 // mode. This way we get the compile-time error checking in debug mode 27 // and best performance in optimized code. 28 template <typename SubType, int kAfterLastRegister> 29 class RegisterBase { 30 public: 31 static constexpr int8_t kCode_no_reg = -1; 32 static constexpr int8_t kNumRegisters = kAfterLastRegister; 33 no_reg()34 static constexpr SubType no_reg() { return SubType{kCode_no_reg}; } 35 from_code(int8_t code)36 static constexpr SubType from_code(int8_t code) { 37 DCHECK(base::IsInRange(static_cast<int>(code), 0, kNumRegisters - 1)); 38 return SubType{code}; 39 } 40 is_valid()41 constexpr bool is_valid() const { return reg_code_ != kCode_no_reg; } 42 code()43 constexpr int8_t code() const { 44 DCHECK(is_valid()); 45 return reg_code_; 46 } 47 48 inline constexpr bool operator==(SubType other) const { 49 return reg_code_ == other.reg_code_; 50 } 51 inline constexpr bool operator!=(SubType other) const { 52 return reg_code_ != other.reg_code_; 53 } 54 55 // Used to print the name of some special registers. GetSpecialRegisterName(int code)56 static const char* GetSpecialRegisterName(int code) { return "UNKNOWN"; } 57 58 protected: RegisterBase(int code)59 explicit constexpr RegisterBase(int code) : reg_code_(code) {} 60 61 private: 62 int8_t reg_code_; 63 STATIC_ASSERT(kAfterLastRegister <= kMaxInt8); 64 }; 65 66 template <typename RegType, 67 typename = decltype(RegisterName(std::declval<RegType>()))> 68 inline std::ostream& operator<<(std::ostream& os, RegType reg) { 69 return os << RegisterName(reg); 70 } 71 72 // Helper macros to define a {RegisterName} method based on a macro list 73 // containing all names. 74 #define DEFINE_REGISTER_NAMES_NAME(name) #name, 75 #define DEFINE_REGISTER_NAMES(RegType, LIST) \ 76 inline const char* RegisterName(RegType reg) { \ 77 static constexpr const char* Names[] = {LIST(DEFINE_REGISTER_NAMES_NAME)}; \ 78 STATIC_ASSERT(arraysize(Names) == RegType::kNumRegisters); \ 79 return reg.is_valid() ? Names[reg.code()] : "invalid"; \ 80 } 81 82 } // namespace internal 83 } // namespace v8 84 85 #endif // V8_CODEGEN_REGISTER_BASE_H_ 86