aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/register.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/register.h')
-rw-r--r--deps/v8/src/register.h126
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_