Line data Source code
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_REGISTER_H_
6 : #define V8_REGISTER_H_
7 :
8 : #include "src/reglist.h"
9 :
10 : namespace v8 {
11 :
12 : namespace internal {
13 :
14 : // Base type for CPU Registers.
15 : //
16 : // 1) We would prefer to use an enum for registers, but enum values are
17 : // assignment-compatible with int, which has caused code-generation bugs.
18 : //
19 : // 2) By not using an enum, we are possibly preventing the compiler from
20 : // doing certain constant folds, which may significantly reduce the
21 : // code generated for some assembly instructions (because they boil down
22 : // to a few constants). If this is a problem, we could change the code
23 : // such that we use an enum in optimized mode, and the class in debug
24 : // mode. This way we get the compile-time error checking in debug mode
25 : // and best performance in optimized code.
26 : template <typename SubType, int kAfterLastRegister>
27 : class RegisterBase {
28 : // Internal enum class; used for calling constexpr methods, where we need to
29 : // pass an integral type as template parameter.
30 : enum class RegisterCode : int { kFirst = 0, kAfterLast = kAfterLastRegister };
31 :
32 : public:
33 : static constexpr int kCode_no_reg = -1;
34 : static constexpr int kNumRegisters = kAfterLastRegister;
35 :
36 : static constexpr SubType no_reg() { return SubType{kCode_no_reg}; }
37 :
38 : template <int code>
39 : static constexpr SubType from_code() {
40 : static_assert(code >= 0 && code < kNumRegisters, "must be valid reg code");
41 : return SubType{code};
42 : }
43 :
44 : constexpr operator RegisterCode() const {
45 : return static_cast<RegisterCode>(reg_code_);
46 : }
47 :
48 : template <RegisterCode reg_code>
49 : static constexpr int code() {
50 : static_assert(
51 : reg_code >= RegisterCode::kFirst && reg_code < RegisterCode::kAfterLast,
52 : "must be valid reg");
53 : return static_cast<int>(reg_code);
54 : }
55 :
56 : template <RegisterCode reg_code>
57 : static constexpr int is_valid() {
58 : return static_cast<int>(reg_code) != kCode_no_reg;
59 : }
60 :
61 : template <RegisterCode reg_code>
62 : static constexpr RegList bit() {
63 : return is_valid<reg_code>() ? RegList{1} << code<reg_code>() : RegList{};
64 : }
65 :
66 : static SubType from_code(int code) {
67 : DCHECK_LE(0, code);
68 : DCHECK_GT(kNumRegisters, code);
69 : return SubType{code};
70 : }
71 :
72 : // Constexpr version (pass registers as template parameters).
73 : template <RegisterCode... reg_codes>
74 : static constexpr RegList ListOf() {
75 : return CombineRegLists(RegisterBase::bit<reg_codes>()...);
76 : }
77 :
78 : // Non-constexpr version (pass registers as method parameters).
79 : template <typename... Register>
80 : static RegList ListOf(Register... regs) {
81 : return CombineRegLists(regs.bit()...);
82 : }
83 :
84 615344 : constexpr bool is_valid() const { return reg_code_ != kCode_no_reg; }
85 :
86 : int code() const {
87 : DCHECK(is_valid());
88 7693555 : return reg_code_;
89 : }
90 :
91 614304 : RegList bit() const { return is_valid() ? RegList{1} << code() : RegList{}; }
92 :
93 : inline constexpr bool operator==(SubType other) const {
94 750043 : return reg_code_ == other.reg_code_;
95 : }
96 : inline constexpr bool operator!=(SubType other) const {
97 728973 : return reg_code_ != other.reg_code_;
98 : }
99 :
100 : // Used to print the name of some special registers.
101 : static const char* GetSpecialRegisterName(int code) { return "UNKNOWN"; }
102 :
103 : protected:
104 : explicit constexpr RegisterBase(int code) : reg_code_(code) {}
105 : int reg_code_;
106 : };
107 :
108 : template <typename RegType,
109 : typename = decltype(RegisterName(std::declval<RegType>()))>
110 : inline std::ostream& operator<<(std::ostream& os, RegType reg) {
111 335 : return os << RegisterName(reg);
112 : }
113 :
114 : // Helper macros to define a {RegisterName} method based on a macro list
115 : // containing all names.
116 : #define DEFINE_REGISTER_NAMES_NAME(name) #name,
117 : #define DEFINE_REGISTER_NAMES(RegType, LIST) \
118 : inline const char* RegisterName(RegType reg) { \
119 : static constexpr const char* Names[] = {LIST(DEFINE_REGISTER_NAMES_NAME)}; \
120 : STATIC_ASSERT(arraysize(Names) == RegType::kNumRegisters); \
121 : return reg.is_valid() ? Names[reg.code()] : "invalid"; \
122 : }
123 :
124 : } // namespace internal
125 : } // namespace v8
126 : #endif // V8_REGISTER_H_
|