• 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_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