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_H_ 6 #define V8_CODEGEN_REGISTER_H_ 7 8 #include "src/base/bounds.h" 9 #include "src/codegen/reglist.h" 10 11 namespace v8 { 12 13 namespace internal { 14 15 // Base type for CPU Registers. 16 // 17 // 1) We would prefer to use an enum for registers, but enum values are 18 // assignment-compatible with int, which has caused code-generation bugs. 19 // 20 // 2) By not using an enum, we are possibly preventing the compiler from 21 // doing certain constant folds, which may significantly reduce the 22 // code generated for some assembly instructions (because they boil down 23 // to a few constants). If this is a problem, we could change the code 24 // such that we use an enum in optimized mode, and the class in debug 25 // mode. This way we get the compile-time error checking in debug mode 26 // and best performance in optimized code. 27 template <typename SubType, int kAfterLastRegister> 28 class RegisterBase { 29 public: 30 static constexpr int kCode_no_reg = -1; 31 static constexpr int kNumRegisters = kAfterLastRegister; 32 no_reg()33 static constexpr SubType no_reg() { return SubType{kCode_no_reg}; } 34 from_code(int code)35 static constexpr SubType from_code(int code) { 36 CONSTEXPR_DCHECK(base::IsInRange(code, 0, kNumRegisters - 1)); 37 return SubType{code}; 38 } 39 40 template <typename... Register> ListOf(Register...regs)41 static constexpr RegList ListOf(Register... regs) { 42 return CombineRegLists(regs.bit()...); 43 } 44 is_valid()45 constexpr bool is_valid() const { return reg_code_ != kCode_no_reg; } 46 code()47 constexpr int code() const { 48 CONSTEXPR_DCHECK(is_valid()); 49 return reg_code_; 50 } 51 bit()52 constexpr RegList bit() const { 53 return is_valid() ? RegList{1} << code() : RegList{}; 54 } 55 56 inline constexpr bool operator==(SubType other) const { 57 return reg_code_ == other.reg_code_; 58 } 59 inline constexpr bool operator!=(SubType other) const { 60 return reg_code_ != other.reg_code_; 61 } 62 63 // Used to print the name of some special registers. GetSpecialRegisterName(int code)64 static const char* GetSpecialRegisterName(int code) { return "UNKNOWN"; } 65 66 protected: RegisterBase(int code)67 explicit constexpr RegisterBase(int code) : reg_code_(code) {} 68 69 private: 70 int reg_code_; 71 }; 72 73 // Whether padding is needed for the given stack argument count. 74 bool ShouldPadArguments(int argument_count); 75 76 template <typename RegType, 77 typename = decltype(RegisterName(std::declval<RegType>()))> 78 inline std::ostream& operator<<(std::ostream& os, RegType reg) { 79 return os << RegisterName(reg); 80 } 81 82 // Helper macros to define a {RegisterName} method based on a macro list 83 // containing all names. 84 #define DEFINE_REGISTER_NAMES_NAME(name) #name, 85 #define DEFINE_REGISTER_NAMES(RegType, LIST) \ 86 inline const char* RegisterName(RegType reg) { \ 87 static constexpr const char* Names[] = {LIST(DEFINE_REGISTER_NAMES_NAME)}; \ 88 STATIC_ASSERT(arraysize(Names) == RegType::kNumRegisters); \ 89 return reg.is_valid() ? Names[reg.code()] : "invalid"; \ 90 } 91 92 } // namespace internal 93 } // namespace v8 94 #endif // V8_CODEGEN_REGISTER_H_ 95