diff options
Diffstat (limited to 'deps/v8/src/register.h')
-rw-r--r-- | deps/v8/src/register.h | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/deps/v8/src/register.h b/deps/v8/src/register.h new file mode 100644 index 0000000000..f1f803a340 --- /dev/null +++ b/deps/v8/src/register.h @@ -0,0 +1,126 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_REGISTER_H_ +#define V8_REGISTER_H_ + +#include "src/reglist.h" + +namespace v8 { + +namespace internal { + +// Base type for CPU Registers. +// +// 1) We would prefer to use an enum for registers, but enum values are +// assignment-compatible with int, which has caused code-generation bugs. +// +// 2) By not using an enum, we are possibly preventing the compiler from +// doing certain constant folds, which may significantly reduce the +// code generated for some assembly instructions (because they boil down +// to a few constants). If this is a problem, we could change the code +// such that we use an enum in optimized mode, and the class in debug +// mode. This way we get the compile-time error checking in debug mode +// and best performance in optimized code. +template <typename SubType, int kAfterLastRegister> +class RegisterBase { + // Internal enum class; used for calling constexpr methods, where we need to + // pass an integral type as template parameter. + enum class RegisterCode : int { kFirst = 0, kAfterLast = kAfterLastRegister }; + + public: + static constexpr int kCode_no_reg = -1; + static constexpr int kNumRegisters = kAfterLastRegister; + + static constexpr SubType no_reg() { return SubType{kCode_no_reg}; } + + template <int code> + static constexpr SubType from_code() { + static_assert(code >= 0 && code < kNumRegisters, "must be valid reg code"); + return SubType{code}; + } + + constexpr operator RegisterCode() const { + return static_cast<RegisterCode>(reg_code_); + } + + template <RegisterCode reg_code> + static constexpr int code() { + static_assert( + reg_code >= RegisterCode::kFirst && reg_code < RegisterCode::kAfterLast, + "must be valid reg"); + return static_cast<int>(reg_code); + } + + template <RegisterCode reg_code> + static constexpr int is_valid() { + return static_cast<int>(reg_code) != kCode_no_reg; + } + + template <RegisterCode reg_code> + static constexpr RegList bit() { + return is_valid<reg_code>() ? RegList{1} << code<reg_code>() : RegList{}; + } + + static SubType from_code(int code) { + DCHECK_LE(0, code); + DCHECK_GT(kNumRegisters, code); + return SubType{code}; + } + + // Constexpr version (pass registers as template parameters). + template <RegisterCode... reg_codes> + static constexpr RegList ListOf() { + return CombineRegLists(RegisterBase::bit<reg_codes>()...); + } + + // Non-constexpr version (pass registers as method parameters). + template <typename... Register> + static RegList ListOf(Register... regs) { + return CombineRegLists(regs.bit()...); + } + + constexpr bool is_valid() const { return reg_code_ != kCode_no_reg; } + + int code() const { + DCHECK(is_valid()); + return reg_code_; + } + + RegList bit() const { return is_valid() ? RegList{1} << code() : RegList{}; } + + inline constexpr bool operator==(SubType other) const { + return reg_code_ == other.reg_code_; + } + inline constexpr bool operator!=(SubType other) const { + return reg_code_ != other.reg_code_; + } + + // Used to print the name of some special registers. + static const char* GetSpecialRegisterName(int code) { return "UNKNOWN"; } + + protected: + explicit constexpr RegisterBase(int code) : reg_code_(code) {} + int reg_code_; +}; + +template <typename RegType, + typename = decltype(RegisterName(std::declval<RegType>()))> +inline std::ostream& operator<<(std::ostream& os, RegType reg) { + return os << RegisterName(reg); +} + +// Helper macros to define a {RegisterName} method based on a macro list +// containing all names. +#define DEFINE_REGISTER_NAMES_NAME(name) #name, +#define DEFINE_REGISTER_NAMES(RegType, LIST) \ + inline const char* RegisterName(RegType reg) { \ + static constexpr const char* Names[] = {LIST(DEFINE_REGISTER_NAMES_NAME)}; \ + STATIC_ASSERT(arraysize(Names) == RegType::kNumRegisters); \ + return reg.is_valid() ? Names[reg.code()] : "invalid"; \ + } + +} // namespace internal +} // namespace v8 +#endif // V8_REGISTER_H_ |