blob: 2aa4c0ecdfb98de1de79dd8d60a26f3de91bb0d9 (
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
|
// SPDX-License-Identifier: GPL-3.0-or-later
#include "rcc/MC/MCContext.h"
#include <cstdint>
#include <limits>
#include <memory>
#include <string>
#include <string_view>
#include <utility>
namespace rcc::mc {
namespace {
[[nodiscard]] bool isValidName(std::string_view Name) noexcept {
if (Name.empty())
return false;
for (const char RawCharacter : Name) {
const auto Character = static_cast<unsigned char>(RawCharacter);
if (Character == 0 || Character == '\n' || Character == '\r' || Character == 0x7fU)
return false;
}
return true;
}
} // namespace
Expected<MCSymbolRef> MCContext::getOrCreateSymbol(std::string Name, MCSymbolKind Kind) {
if (!isValidName(Name))
return makeUnexpected(ErrorCode::InvalidArgument, "MC symbol has an invalid name");
const auto Position = Symbols.find(Name);
if (Position != Symbols.end()) {
const MCSymbolKind ExistingKind = Position->second->kind();
if (Kind != MCSymbolKind::Generic && ExistingKind != MCSymbolKind::Generic &&
ExistingKind != Kind) {
return makeUnexpected(ErrorCode::InvalidArgument,
"MC symbol name is already used by a different symbol kind");
}
return Position->second;
}
MCSymbolRef Result(new MCSymbol(std::move(Name), Kind));
Symbols.emplace(std::string(Result->name()), Result);
return Result;
}
Expected<MCSymbolRef> MCContext::createTemporarySymbol(std::string_view Prefix) {
if (!isValidName(Prefix))
return makeUnexpected(ErrorCode::InvalidArgument, "temporary MC symbol prefix is invalid");
if (NextTemporarySymbol == std::numeric_limits<std::uint64_t>::max()) {
return makeUnexpected(ErrorCode::InternalError, "temporary MC symbol sequence is exhausted");
}
while (true) {
std::string Name(Prefix);
Name += std::to_string(NextTemporarySymbol++);
if (Symbols.contains(Name))
continue;
return getOrCreateSymbol(std::move(Name), MCSymbolKind::Temporary);
}
}
MCSymbolRef MCContext::symbol(std::string_view Name) const noexcept {
const auto Position = Symbols.find(Name);
return Position == Symbols.end() ? MCSymbolRef{} : Position->second;
}
Expected<MCSectionRef> MCContext::getOrCreateSection(MCSectionDesc Description) {
auto Verification = Description.verify();
if (!Verification)
return std::unexpected(Verification.error());
const auto Position = Sections.find(Description.Name);
if (Position != Sections.end()) {
MCSectionDesc ExistingDescription = Position->second->description();
ExistingDescription.Alignment = Description.Alignment;
if (ExistingDescription != Description) {
return makeUnexpected(ErrorCode::InvalidArgument,
"MC section name is already used by a different description");
}
return Position->second;
}
MCSectionRef Result(new MCSection(std::move(Description)));
Sections.emplace(std::string(Result->name()), Result);
return Result;
}
MCSectionRef MCContext::section(std::string_view Name) const noexcept {
const auto Position = Sections.find(Name);
return Position == Sections.end() ? MCSectionRef{} : Position->second;
}
} // namespace rcc::mc
|