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
|
// SPDX-License-Identifier: GPL-3.0-or-later
#include "rcc/CodeGen/MachineMetadata.h"
#include <cstddef>
#include <string>
#include <unordered_set>
#include <utility>
namespace rcc {
namespace {
[[nodiscard]] Expected<void> verifyNodeElements(const MachineMetadataNode &Node) {
for (const MachineMetadataElement &Element : Node.Elements) {
if (!Element.isValid()) {
return makeUnexpected(ErrorCode::VerificationError,
"machine metadata tuple contains an invalid element");
}
const MachineMetadataReference *Reference = Element.reference();
if (Reference != nullptr && !Reference->isValid()) {
return makeUnexpected(ErrorCode::VerificationError,
"machine metadata tuple contains an invalid reference");
}
}
return {};
}
} // namespace
MachineMetadataElement MachineMetadataElement::null() {
return MachineMetadataElement(NullValue{});
}
Expected<MachineMetadataElement>
MachineMetadataElement::reference(MachineMetadataReference Reference) {
if (!Reference.isValid()) {
return makeUnexpected(ErrorCode::InvalidArgument,
"machine metadata element reference must be valid");
}
return MachineMetadataElement(Reference);
}
MachineMetadataElement MachineMetadataElement::string(std::string Value) {
return MachineMetadataElement(std::move(Value));
}
Expected<void> MachineMetadataInfo::addNode(MachineMetadataNode Node) {
auto Verification = verifyNodeElements(Node);
if (!Verification)
return std::unexpected(Verification.error());
if (SlotToIndex.contains(Node.Slot)) {
return makeUnexpected(ErrorCode::InvalidArgument, "machine metadata slot is already defined");
}
const std::size_t Index = Nodes.size();
SlotToIndex.emplace(Node.Slot, Index);
Nodes.push_back(std::move(Node));
return {};
}
const MachineMetadataNode *MachineMetadataInfo::node(std::uint32_t Slot) const noexcept {
const auto Position = SlotToIndex.find(Slot);
if (Position == SlotToIndex.end())
return nullptr;
return &Nodes[Position->second];
}
Expected<void> MachineMetadataInfo::verify() const {
if (SlotToIndex.size() != Nodes.size()) {
return makeUnexpected(ErrorCode::VerificationError,
"machine metadata slot index has an inconsistent size");
}
std::unordered_set<std::uint32_t> Slots;
for (std::size_t Index = 0; Index < Nodes.size(); ++Index) {
const MachineMetadataNode &Node = Nodes[Index];
if (!Slots.insert(Node.Slot).second) {
return makeUnexpected(ErrorCode::VerificationError,
"machine metadata contains duplicate slot definitions");
}
const auto Position = SlotToIndex.find(Node.Slot);
if (Position == SlotToIndex.end() || Position->second != Index) {
return makeUnexpected(ErrorCode::VerificationError,
"machine metadata slot index is inconsistent");
}
auto ElementVerification = verifyNodeElements(Node);
if (!ElementVerification)
return ElementVerification;
}
for (const MachineMetadataNode &Node : Nodes) {
for (const MachineMetadataElement &Element : Node.Elements) {
const MachineMetadataReference *Reference = Element.reference();
if (Reference != nullptr && Reference->scope() == MachineMetadataScope::MachineFunction &&
!Slots.contains(Reference->slot())) {
return makeUnexpected(ErrorCode::VerificationError,
"machine metadata tuple references an undefined function slot");
}
}
}
return {};
}
Expected<MachineMetadataInfo> MachineMetadataInfo::clone() const {
auto Verification = verify();
if (!Verification)
return std::unexpected(Verification.error());
MachineMetadataInfo Result;
for (const MachineMetadataNode &Node : Nodes) {
auto AddResult = Result.addNode(Node);
if (!AddResult)
return std::unexpected(AddResult.error());
}
return Result;
}
Expected<void> verifyMachineMetadataReference(MachineMetadataReference Reference,
const MachineMetadataInfo &Metadata) {
if (!Reference.isValid()) {
return makeUnexpected(ErrorCode::VerificationError, "machine metadata reference is invalid");
}
if (Reference.scope() == MachineMetadataScope::MachineFunction &&
Metadata.node(Reference.slot()) == nullptr) {
return makeUnexpected(ErrorCode::VerificationError,
"machine metadata reference uses an undefined function slot");
}
return {};
}
} // namespace rcc
|