1// Copyright 2022 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_MAGLEV_MAGLEV_REGALLOC_DATA_H_
6#define V8_MAGLEV_MAGLEV_REGALLOC_DATA_H_
7
8#include "src/base/pointer-with-payload.h"
9#include "src/codegen/register.h"
10#include "src/compiler/backend/instruction.h"
11
12namespace v8 {
13namespace internal {
14namespace maglev {
15
16class ValueNode;
17
18#define COUNT(V) +1
19static constexpr int kAllocatableGeneralRegisterCount =
20    ALLOCATABLE_GENERAL_REGISTERS(COUNT);
21#undef COUNT
22
23struct RegisterStateFlags {
24  // TODO(v8:7700): Use the good old Flags mechanism.
25  static constexpr int kIsMergeShift = 0;
26  static constexpr int kIsInitializedShift = 1;
27
28  const bool is_initialized = false;
29  const bool is_merge = false;
30
31  explicit constexpr operator uintptr_t() const {
32    return (is_initialized ? 1 << kIsInitializedShift : 0) |
33           (is_merge ? 1 << kIsMergeShift : 0);
34  }
35  constexpr explicit RegisterStateFlags(uintptr_t state)
36      : is_initialized((state & (1 << kIsInitializedShift)) != 0),
37        is_merge((state & (1 << kIsMergeShift)) != 0) {}
38  constexpr RegisterStateFlags(bool is_initialized, bool is_merge)
39      : is_initialized(is_initialized), is_merge(is_merge) {}
40};
41constexpr bool operator==(const RegisterStateFlags& left,
42                          const RegisterStateFlags& right) {
43  return left.is_initialized == right.is_initialized &&
44         left.is_merge == right.is_merge;
45}
46
47typedef base::PointerWithPayload<void, RegisterStateFlags, 2> RegisterState;
48
49struct RegisterMerge {
50  compiler::AllocatedOperand* operands() {
51    return reinterpret_cast<compiler::AllocatedOperand*>(this + 1);
52  }
53  compiler::AllocatedOperand& operand(size_t i) { return operands()[i]; }
54
55  ValueNode* node;
56};
57
58inline bool LoadMergeState(RegisterState state, RegisterMerge** merge) {
59  DCHECK(state.GetPayload().is_initialized);
60  if (state.GetPayload().is_merge) {
61    *merge = static_cast<RegisterMerge*>(state.GetPointer());
62    return true;
63  }
64  *merge = nullptr;
65  return false;
66}
67
68inline bool LoadMergeState(RegisterState state, ValueNode** node,
69                           RegisterMerge** merge) {
70  DCHECK(state.GetPayload().is_initialized);
71  if (LoadMergeState(state, merge)) {
72    *node = (*merge)->node;
73    return true;
74  }
75  *node = static_cast<ValueNode*>(state.GetPointer());
76  return false;
77}
78
79}  // namespace maglev
80}  // namespace internal
81}  // namespace v8
82
83#endif  // V8_MAGLEV_MAGLEV_REGALLOC_DATA_H_
84