aboutsummaryrefslogtreecommitdiff
path: root/backend/lib/CodeGen/Register.cpp
blob: 0af26c711134b79d05b97852ca6edda8915f20af (plain)
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
// SPDX-License-Identifier: GPL-3.0-or-later

#include "rcc/CodeGen/Register.h"

#include <string>

namespace rcc {
namespace {

constexpr std::uint64_t MaximumRegisterIndex = (std::uint64_t{1} << 31) - 1;

} // namespace

Expected<PhysicalRegister> PhysicalRegister::create(std::uint64_t Number) {
  if (Number == 0 || Number > MaximumRegisterIndex) {
    return makeUnexpected(ErrorCode::InvalidArgument,
                          "physical register number must be in the range [1, 2147483647]");
  }
  return PhysicalRegister(static_cast<std::uint32_t>(Number));
}

Expected<Register> Register::makePhysical(std::uint64_t Number) {
  auto PhysReg = PhysicalRegister::create(Number);
  if (!PhysReg)
    return std::unexpected(PhysReg.error());
  return fromPhysical(*PhysReg);
}

Expected<Register> Register::makeVirtual(std::uint64_t Index) {
  if (Index > MaximumRegisterIndex) {
    return makeUnexpected(ErrorCode::InvalidArgument, "virtual register index must fit in 31 bits");
  }
  return Register(VirtualBit | static_cast<std::uint32_t>(Index));
}

std::optional<PhysicalRegister> Register::physicalRegister() const noexcept {
  if (!isPhysical())
    return std::nullopt;
  return PhysicalRegister(OpaqueValue);
}

std::optional<std::uint32_t> Register::virtualIndex() const noexcept {
  if (!isVirtual())
    return std::nullopt;
  return OpaqueValue & IndexMask;
}

std::string Register::toString() const {
  if (isNoRegister())
    return "noreg";
  if (isVirtual())
    return "%" + std::to_string(OpaqueValue & IndexMask);
  return "$physreg" + std::to_string(OpaqueValue);
}

} // namespace rcc