• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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