Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/CGData/StableFunctionMapRecord.cpp
213764 views
1
//===-- StableFunctionMapRecord.cpp ---------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This implements the functionality for the StableFunctionMapRecord class,
10
// including methods for serialization and deserialization of stable function
11
// maps to and from raw and YAML streams. It also includes utilities for
12
// managing function entries and their metadata.
13
//
14
//===----------------------------------------------------------------------===//
15
16
#include "llvm/CGData/StableFunctionMapRecord.h"
17
#include "llvm/Support/EndianStream.h"
18
19
#define DEBUG_TYPE "stable-function-map-record"
20
21
using namespace llvm;
22
using namespace llvm::support;
23
24
LLVM_YAML_IS_SEQUENCE_VECTOR(IndexPairHash)
25
LLVM_YAML_IS_SEQUENCE_VECTOR(StableFunction)
26
27
namespace llvm {
28
namespace yaml {
29
30
template <> struct MappingTraits<IndexPairHash> {
31
static void mapping(IO &IO, IndexPairHash &Key) {
32
IO.mapRequired("InstIndex", Key.first.first);
33
IO.mapRequired("OpndIndex", Key.first.second);
34
IO.mapRequired("OpndHash", Key.second);
35
}
36
};
37
38
template <> struct MappingTraits<StableFunction> {
39
static void mapping(IO &IO, StableFunction &Func) {
40
IO.mapRequired("Hash", Func.Hash);
41
IO.mapRequired("FunctionName", Func.FunctionName);
42
IO.mapRequired("ModuleName", Func.ModuleName);
43
IO.mapRequired("InstCount", Func.InstCount);
44
IO.mapRequired("IndexOperandHashes", Func.IndexOperandHashes);
45
}
46
};
47
48
} // namespace yaml
49
} // namespace llvm
50
51
// Get a sorted vector of StableFunctionEntry pointers.
52
static SmallVector<const StableFunctionMap::StableFunctionEntry *>
53
getStableFunctionEntries(const StableFunctionMap &SFM) {
54
SmallVector<const StableFunctionMap::StableFunctionEntry *> FuncEntries;
55
for (const auto &P : SFM.getFunctionMap())
56
for (auto &Func : P.second)
57
FuncEntries.emplace_back(Func.get());
58
59
llvm::stable_sort(
60
FuncEntries, [&](auto &A, auto &B) {
61
return std::tuple(A->Hash, SFM.getNameForId(A->ModuleNameId),
62
SFM.getNameForId(A->FunctionNameId)) <
63
std::tuple(B->Hash, SFM.getNameForId(B->ModuleNameId),
64
SFM.getNameForId(B->FunctionNameId));
65
});
66
return FuncEntries;
67
}
68
69
// Get a sorted vector of IndexOperandHashes.
70
static IndexOperandHashVecType getStableIndexOperandHashes(
71
const StableFunctionMap::StableFunctionEntry *FuncEntry) {
72
IndexOperandHashVecType IndexOperandHashes;
73
for (auto &[Indices, OpndHash] : *FuncEntry->IndexOperandHashMap)
74
IndexOperandHashes.emplace_back(Indices, OpndHash);
75
// The indices are unique, so we can just sort by the first.
76
llvm::sort(IndexOperandHashes);
77
return IndexOperandHashes;
78
}
79
80
void StableFunctionMapRecord::serialize(
81
raw_ostream &OS, std::vector<CGDataPatchItem> &PatchItems) const {
82
serialize(OS, FunctionMap.get(), PatchItems);
83
}
84
85
void StableFunctionMapRecord::serialize(
86
raw_ostream &OS, const StableFunctionMap *FunctionMap,
87
std::vector<CGDataPatchItem> &PatchItems) {
88
support::endian::Writer Writer(OS, endianness::little);
89
90
// Write Names.
91
ArrayRef<std::string> Names = FunctionMap->getNames();
92
Writer.write<uint32_t>(Names.size());
93
// Remember the position, write back the total size of Names, so we can skip
94
// reading them if needed.
95
const uint64_t NamesByteSizeOffset = Writer.OS.tell();
96
Writer.write<uint64_t>(0);
97
for (auto &Name : Names)
98
Writer.OS << Name << '\0';
99
// Align current position to 4 bytes.
100
uint32_t Padding = offsetToAlignment(Writer.OS.tell(), Align(4));
101
for (uint32_t I = 0; I < Padding; ++I)
102
Writer.OS << '\0';
103
const auto NamesByteSize =
104
Writer.OS.tell() - NamesByteSizeOffset - sizeof(NamesByteSizeOffset);
105
PatchItems.emplace_back(NamesByteSizeOffset, &NamesByteSize, 1);
106
107
// Write StableFunctionEntries whose pointers are sorted.
108
auto FuncEntries = getStableFunctionEntries(*FunctionMap);
109
Writer.write<uint32_t>(FuncEntries.size());
110
111
for (const auto *FuncRef : FuncEntries) {
112
Writer.write<stable_hash>(FuncRef->Hash);
113
Writer.write<uint32_t>(FuncRef->FunctionNameId);
114
Writer.write<uint32_t>(FuncRef->ModuleNameId);
115
Writer.write<uint32_t>(FuncRef->InstCount);
116
117
// Emit IndexOperandHashes sorted from IndexOperandHashMap.
118
IndexOperandHashVecType IndexOperandHashes =
119
getStableIndexOperandHashes(FuncRef);
120
Writer.write<uint32_t>(IndexOperandHashes.size());
121
for (auto &IndexOperandHash : IndexOperandHashes) {
122
Writer.write<uint32_t>(IndexOperandHash.first.first);
123
Writer.write<uint32_t>(IndexOperandHash.first.second);
124
Writer.write<stable_hash>(IndexOperandHash.second);
125
}
126
}
127
}
128
129
void StableFunctionMapRecord::deserialize(const unsigned char *&Ptr,
130
bool ReadStableFunctionMapNames) {
131
// Assert that Ptr is 4-byte aligned
132
assert(((uintptr_t)Ptr % 4) == 0);
133
// Read Names.
134
auto NumNames =
135
endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);
136
// Early exit if there is no name.
137
if (NumNames == 0)
138
return;
139
const auto NamesByteSize =
140
endian::readNext<uint64_t, endianness::little, unaligned>(Ptr);
141
const auto NamesOffset = reinterpret_cast<uintptr_t>(Ptr);
142
if (ReadStableFunctionMapNames) {
143
for (unsigned I = 0; I < NumNames; ++I) {
144
StringRef Name(reinterpret_cast<const char *>(Ptr));
145
Ptr += Name.size() + 1;
146
FunctionMap->getIdOrCreateForName(Name);
147
}
148
// Align Ptr to 4 bytes.
149
Ptr = reinterpret_cast<const uint8_t *>(alignAddr(Ptr, Align(4)));
150
assert(reinterpret_cast<uintptr_t>(Ptr) - NamesOffset == NamesByteSize &&
151
"NamesByteSize does not match the actual size of names");
152
} else {
153
// skip reading Names by advancing the pointer.
154
Ptr = reinterpret_cast<const uint8_t *>(NamesOffset + NamesByteSize);
155
}
156
157
// Read StableFunctionEntries.
158
auto NumFuncs =
159
endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);
160
for (unsigned I = 0; I < NumFuncs; ++I) {
161
auto Hash =
162
endian::readNext<stable_hash, endianness::little, unaligned>(Ptr);
163
auto FunctionNameId =
164
endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);
165
assert(FunctionMap->getNameForId(FunctionNameId) &&
166
"FunctionNameId out of range");
167
auto ModuleNameId =
168
endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);
169
assert(FunctionMap->getNameForId(ModuleNameId) &&
170
"ModuleNameId out of range");
171
auto InstCount =
172
endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);
173
174
// Read IndexOperandHashes to build IndexOperandHashMap
175
auto NumIndexOperandHashes =
176
endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);
177
auto IndexOperandHashMap = std::make_unique<IndexOperandHashMapType>();
178
for (unsigned J = 0; J < NumIndexOperandHashes; ++J) {
179
auto InstIndex =
180
endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);
181
auto OpndIndex =
182
endian::readNext<uint32_t, endianness::little, unaligned>(Ptr);
183
auto OpndHash =
184
endian::readNext<stable_hash, endianness::little, unaligned>(Ptr);
185
assert(InstIndex < InstCount && "InstIndex out of range");
186
187
IndexOperandHashMap->try_emplace({InstIndex, OpndIndex}, OpndHash);
188
}
189
190
// Insert a new StableFunctionEntry into the map.
191
auto FuncEntry = std::make_unique<StableFunctionMap::StableFunctionEntry>(
192
Hash, FunctionNameId, ModuleNameId, InstCount,
193
std::move(IndexOperandHashMap));
194
195
FunctionMap->insert(std::move(FuncEntry));
196
}
197
}
198
199
void StableFunctionMapRecord::serializeYAML(yaml::Output &YOS) const {
200
auto FuncEntries = getStableFunctionEntries(*FunctionMap);
201
SmallVector<StableFunction> Functions;
202
for (const auto *FuncEntry : FuncEntries) {
203
auto IndexOperandHashes = getStableIndexOperandHashes(FuncEntry);
204
Functions.emplace_back(
205
FuncEntry->Hash, *FunctionMap->getNameForId(FuncEntry->FunctionNameId),
206
*FunctionMap->getNameForId(FuncEntry->ModuleNameId),
207
FuncEntry->InstCount, std::move(IndexOperandHashes));
208
}
209
210
YOS << Functions;
211
}
212
213
void StableFunctionMapRecord::deserializeYAML(yaml::Input &YIS) {
214
std::vector<StableFunction> Funcs;
215
YIS >> Funcs;
216
for (auto &Func : Funcs)
217
FunctionMap->insert(Func);
218
YIS.nextDocument();
219
}
220
221