aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/include/llvm/CodeGen/Register.h
blob: d7057cfb76e0ed7667c7afeca0a06116548b2835 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
//===-- llvm/CodeGen/Register.h ---------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CODEGEN_REGISTER_H
#define LLVM_CODEGEN_REGISTER_H

#include "llvm/MC/MCRegister.h"
#include <cassert>

namespace llvm {

/// Wrapper class representing virtual and physical registers. Should be passed
/// by value.
class Register {
  unsigned Reg;

public:
  constexpr Register(unsigned Val = 0): Reg(Val) {}
  constexpr Register(MCRegister Val): Reg(Val) {}

  // Register numbers can represent physical registers, virtual registers, and
  // sometimes stack slots. The unsigned values are divided into these ranges:
  //
  //   0           Not a register, can be used as a sentinel.
  //   [1;2^30)    Physical registers assigned by TableGen.
  //   [2^30;2^31) Stack slots. (Rarely used.)
  //   [2^31;2^32) Virtual registers assigned by MachineRegisterInfo.
  //
  // Further sentinels can be allocated from the small negative integers.
  // DenseMapInfo<unsigned> uses -1u and -2u.
  static_assert(std::numeric_limits<decltype(Reg)>::max() >= 0xFFFFFFFF,
                "Reg isn't large enough to hold full range.");

  /// isStackSlot - Sometimes it is useful the be able to store a non-negative
  /// frame index in a variable that normally holds a register. isStackSlot()
  /// returns true if Reg is in the range used for stack slots.
  ///
  /// FIXME: remove in favor of member.
  static bool isStackSlot(unsigned Reg) {
    return MCRegister::isStackSlot(Reg);
  }

  /// Return true if this is a stack slot.
  bool isStack() const { return MCRegister::isStackSlot(Reg); }

  /// Compute the frame index from a register value representing a stack slot.
  static int stackSlot2Index(Register Reg) {
    assert(Reg.isStack() && "Not a stack slot");
    return int(Reg - MCRegister::FirstStackSlot);
  }

  /// Convert a non-negative frame index to a stack slot register value.
  static Register index2StackSlot(int FI) {
    assert(FI >= 0 && "Cannot hold a negative frame index.");
    return Register(FI + MCRegister::FirstStackSlot);
  }

  /// Return true if the specified register number is in
  /// the physical register namespace.
  static bool isPhysicalRegister(unsigned Reg) {
    return MCRegister::isPhysicalRegister(Reg);
  }

  /// Return true if the specified register number is in
  /// the virtual register namespace.
  static bool isVirtualRegister(unsigned Reg) {
    return Reg & MCRegister::VirtualRegFlag && !isStackSlot(Reg);
  }

  /// Convert a virtual register number to a 0-based index.
  /// The first virtual register in a function will get the index 0.
  static unsigned virtReg2Index(Register Reg) {
    assert(isVirtualRegister(Reg) && "Not a virtual register");
    return Reg & ~MCRegister::VirtualRegFlag;
  }

  /// Convert a 0-based index to a virtual register number.
  /// This is the inverse operation of VirtReg2IndexFunctor below.
  static Register index2VirtReg(unsigned Index) {
    assert(Index < (1u << 31) && "Index too large for virtual register range.");
    return Index | MCRegister::VirtualRegFlag;
  }

  /// Return true if the specified register number is in the virtual register
  /// namespace.
  bool isVirtual() const {
    return isVirtualRegister(Reg);
  }

  /// Return true if the specified register number is in the physical register
  /// namespace.
  bool isPhysical() const {
    return isPhysicalRegister(Reg);
  }

  /// Convert a virtual register number to a 0-based index. The first virtual
  /// register in a function will get the index 0.
  unsigned virtRegIndex() const {
    return virtReg2Index(Reg);
  }

  constexpr operator unsigned() const {
    return Reg;
  }

  unsigned id() const { return Reg; }

  operator MCRegister() const {
    return MCRegister(Reg);
  }

  /// Utility to check-convert this value to a MCRegister. The caller is
  /// expected to have already validated that this Register is, indeed,
  /// physical.
  MCRegister asMCReg() const {
    assert(Reg == MCRegister::NoRegister ||
           MCRegister::isPhysicalRegister(Reg));
    return MCRegister(Reg);
  }

  bool isValid() const { return Reg != MCRegister::NoRegister; }

  /// Comparisons between register objects
  bool operator==(const Register &Other) const { return Reg == Other.Reg; }
  bool operator!=(const Register &Other) const { return Reg != Other.Reg; }
  bool operator==(const MCRegister &Other) const { return Reg == Other.id(); }
  bool operator!=(const MCRegister &Other) const { return Reg != Other.id(); }

  /// Comparisons against register constants. E.g.
  /// * R == AArch64::WZR
  /// * R == 0
  /// * R == VirtRegMap::NO_PHYS_REG
  bool operator==(unsigned Other) const { return Reg == Other; }
  bool operator!=(unsigned Other) const { return Reg != Other; }
  bool operator==(int Other) const { return Reg == unsigned(Other); }
  bool operator!=(int Other) const { return Reg != unsigned(Other); }
  // MSVC requires that we explicitly declare these two as well.
  bool operator==(MCPhysReg Other) const { return Reg == unsigned(Other); }
  bool operator!=(MCPhysReg Other) const { return Reg != unsigned(Other); }
};

// Provide DenseMapInfo for Register
template<> struct DenseMapInfo<Register> {
  static inline unsigned getEmptyKey() {
    return DenseMapInfo<unsigned>::getEmptyKey();
  }
  static inline unsigned getTombstoneKey() {
    return DenseMapInfo<unsigned>::getTombstoneKey();
  }
  static unsigned getHashValue(const Register &Val) {
    return DenseMapInfo<unsigned>::getHashValue(Val.id());
  }
  static bool isEqual(const Register &LHS, const Register &RHS) {
    return DenseMapInfo<unsigned>::isEqual(LHS.id(), RHS.id());
  }
};

}

#endif // ifndef LLVM_CODEGEN_REGISTER_H