aboutsummaryrefslogtreecommitdiff
path: root/backend/include/rcc/CodeGen/MachineJumpTableInfo.h
blob: b22ea50cd4f04d4b06477be64f9d70a15625e6d7 (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
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
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef RCC_CODEGEN_MACHINEJUMPTABLEINFO_H
#define RCC_CODEGEN_MACHINEJUMPTABLEINFO_H

#include "rcc/CodeGen/MachineIRTypes.h"
#include "rcc/CodeGen/MachineMemOperand.h"
#include "rcc/Support/Error.h"

#include <cstddef>
#include <cstdint>
#include <optional>
#include <span>
#include <utility>
#include <variant>
#include <vector>

namespace rcc {

class MachineBasicBlock;
class MachineFunction;

enum class JumpTableEntryEncoding : std::uint8_t {
  BlockAddress,
  GPRelative64BlockAddress,
  GPRelative32BlockAddress,
  LabelDifference32,
  LabelDifference64,
  Inline,
  Custom32,
  Target,
  Count,
};

struct JumpTablePlacement final {
  bool InTextSection = true;
  bool UniqueSection = false;
  std::optional<std::uint64_t> MaximumDistance;
  std::uint64_t TargetFlags = 0;

  friend bool operator==(const JumpTablePlacement &Left, const JumpTablePlacement &Right) = default;
};

struct MachineJumpTableDesc final {
  JumpTableEntryEncoding Encoding = JumpTableEntryEncoding::BlockAddress;
  std::uint8_t EntrySize = 8;
  Alignment Align;
  std::vector<MachineBasicBlock *> Targets;
  JumpTablePlacement Placement;
  std::uint32_t TargetEncoding = 0;

  friend bool operator==(const MachineJumpTableDesc &Left,
                         const MachineJumpTableDesc &Right) = default;
};

class MachineJumpTableEntry final {
public:
  [[nodiscard]] JumpTableIndex index() const noexcept {
    return Index;
  }

  [[nodiscard]] bool isTombstone() const noexcept {
    return std::holds_alternative<std::monostate>(Description);
  }

  [[nodiscard]] bool isPending() const noexcept {
    return std::holds_alternative<PendingDescription>(Description);
  }

  [[nodiscard]] const MachineJumpTableDesc *description() const noexcept {
    return std::get_if<MachineJumpTableDesc>(&Description);
  }

private:
  struct PendingDescription final {};

  MachineJumpTableEntry(JumpTableIndex Index, MachineJumpTableDesc Description)
      : Index(Index), Description(std::move(Description)) {}
  explicit MachineJumpTableEntry(JumpTableIndex Index)
      : Index(Index), Description(PendingDescription{}) {}

  JumpTableIndex Index;
  std::variant<std::monostate, PendingDescription, MachineJumpTableDesc> Description;

  friend class MachineJumpTableInfo;
};

class MachineJumpTableInfo final {
public:
  explicit MachineJumpTableInfo(MachineFunction &Owner) noexcept : Owner(&Owner) {}

  MachineJumpTableInfo(const MachineJumpTableInfo &) = delete;
  MachineJumpTableInfo &operator=(const MachineJumpTableInfo &) = delete;
  MachineJumpTableInfo(MachineJumpTableInfo &&) = delete;
  MachineJumpTableInfo &operator=(MachineJumpTableInfo &&) = delete;
  ~MachineJumpTableInfo() = default;

  [[nodiscard]] Expected<JumpTableIndex> createTable(MachineJumpTableDesc Description);
  [[nodiscard]] Expected<JumpTableIndex> reserveTable();
  [[nodiscard]] Expected<void> defineReservedTable(JumpTableIndex Index,
                                                   MachineJumpTableDesc Description);
  [[nodiscard]] Expected<void> updateTable(JumpTableIndex Index, MachineJumpTableDesc Description);
  [[nodiscard]] Expected<void> eraseTable(JumpTableIndex Index);

  [[nodiscard]] const MachineJumpTableEntry *table(JumpTableIndex Index) const noexcept;
  [[nodiscard]] std::span<const MachineJumpTableEntry> tables() const noexcept {
    return Tables;
  }

  [[nodiscard]] std::size_t liveTableCount() const noexcept;

  [[nodiscard]] bool isFrozen() const noexcept {
    return Frozen;
  }

  [[nodiscard]] Expected<void> freeze();
  [[nodiscard]] Expected<void> verify() const;

private:
  [[nodiscard]] Expected<void> verifyDescription(const MachineJumpTableDesc &Description) const;
  [[nodiscard]] Expected<MachineJumpTableEntry *> mutableTable(JumpTableIndex Index);

  MachineFunction *Owner;
  std::vector<MachineJumpTableEntry> Tables;
  bool Frozen = false;
};

} // namespace rcc

#endif // RCC_CODEGEN_MACHINEJUMPTABLEINFO_H