LLVM 24.0.0git
BBAddrMapYAML.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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/// \file
10/// This file defines the YAMLIO mappings for the format-agnostic BB address
11/// map YAML types declared in BBAddrMapYAML.h.
12///
13//===----------------------------------------------------------------------===//
14
18#include "llvm/Support/Errc.h"
20
21namespace llvm {
22namespace yaml {
23
25 IO &IO, BBAddrMapYAML::BBAddrMapEntry &E) {
26 assert(IO.getContext() && "The IO context is not initialized");
27 IO.mapRequired("Version", E.Version);
28 IO.mapOptional("Feature", E.Feature, Hex16(0));
29 IO.mapOptional("FuncGUID", E.FuncGUID);
30 IO.mapOptional("NumBBRanges", E.NumBBRanges);
31 IO.mapOptional("BBRanges", E.BBRanges);
32}
33
35 IO &IO, BBAddrMapYAML::BBAddrMapEntry::BBRangeEntry &E) {
36 IO.mapOptional("BaseAddress", E.BaseAddress, Hex64(0));
37 IO.mapOptional("NumBlocks", E.NumBlocks);
38 IO.mapOptional("BBEntries", E.BBEntries);
39}
40
42 IO &IO, BBAddrMapYAML::BBAddrMapEntry::BBEntry &E) {
43 assert(IO.getContext() && "The IO context is not initialized");
44 IO.mapOptional("ID", E.ID);
45 IO.mapRequired("AddressOffset", E.AddressOffset);
46 IO.mapRequired("Size", E.Size);
47 IO.mapRequired("Metadata", E.Metadata);
48 IO.mapOptional("CallsiteEndOffsets", E.CallsiteEndOffsets);
49 IO.mapOptional("Hash", E.Hash);
50}
51
53 IO &IO, BBAddrMapYAML::PGOAnalysisMapEntry &E) {
54 assert(IO.getContext() && "The IO context is not initialized");
55 IO.mapOptional("FuncEntryCount", E.FuncEntryCount);
56 IO.mapOptional("PGOBBEntries", E.PGOBBEntries);
57}
58
60 IO &IO, BBAddrMapYAML::PGOAnalysisMapEntry::PGOBBEntry &E) {
61 assert(IO.getContext() && "The IO context is not initialized");
62 IO.mapOptional("BBFreq", E.BBFreq);
63 IO.mapOptional("PostLinkBBFreq", E.PostLinkBBFreq);
64 IO.mapOptional("Successors", E.Successors);
65}
66
67void MappingTraits<
68 BBAddrMapYAML::PGOAnalysisMapEntry::PGOBBEntry::SuccessorEntry>::
69 mapping(IO &IO,
70 BBAddrMapYAML::PGOAnalysisMapEntry::PGOBBEntry::SuccessorEntry &E) {
71 assert(IO.getContext() && "The IO context is not initialized");
72 IO.mapRequired("ID", E.ID);
73 IO.mapRequired("BrProb", E.BrProb);
74 IO.mapOptional("PostLinkBrFreq", E.PostLinkBrFreq);
75}
76
77} // end namespace yaml
78
79namespace BBAddrMapYAML {
80
82 const std::vector<PGOAnalysisMapEntry> *PGOAnalyses,
84 llvm::endianness Endian, unsigned AddressSize) {
85 assert((AddressSize == 4 || AddressSize == 8) && "invalid address size");
86 for (const auto &[Idx, E] : llvm::enumerate(Entries)) {
87 // Write version and feature values.
88 if (E.Version > 6)
89 WithColor::warning() << "unsupported BB address map version: "
90 << static_cast<int>(E.Version)
91 << "; encoding using the most recent version";
92 CBA.write(E.Version);
93 if (E.Version < 5)
94 CBA.write(static_cast<uint8_t>(E.Feature));
95 else
96 CBA.write<uint16_t>(E.Feature, Endian);
97 auto FeatureOrErr = llvm::object::BBAddrMap::Features::decode(E.Feature);
98 if (!FeatureOrErr) {
99 // Invalid feature: warn and skip the entry.
100 WithColor::warning() << toString(FeatureOrErr.takeError());
101 continue;
102 }
103 // Write the function GUID. This is emitted when either the feature is
104 // enabled or 'FuncGUID' is specified, which allows testing mismatches.
105 if (!FeatureOrErr->FuncGUID && E.FuncGUID.has_value())
106 WithColor::warning() << "feature value(" << E.Feature
107 << ") does not support function GUID.";
108 if (FeatureOrErr->FuncGUID || E.FuncGUID.has_value())
109 CBA.write<uint64_t>(E.FuncGUID.value_or(llvm::yaml::Hex64(0)), Endian);
110 bool MultiBBRangeFeatureEnabled = FeatureOrErr->MultiBBRange;
111 bool MultiBBRange =
112 MultiBBRangeFeatureEnabled ||
113 (E.NumBBRanges.has_value() && E.NumBBRanges.value() != 1) ||
114 (E.BBRanges && E.BBRanges->size() != 1);
115 if (MultiBBRange && !MultiBBRangeFeatureEnabled)
116 WithColor::warning() << "feature value(" << E.Feature
117 << ") does not support multiple BB ranges.";
118 if (MultiBBRange) {
119 // Write the number of basic block ranges, which is overridden by the
120 // 'NumBBRanges' field when specified.
121 uint64_t NumBBRanges =
122 E.NumBBRanges.value_or(E.BBRanges ? E.BBRanges->size() : 0);
123 CBA.writeULEB128(NumBBRanges);
124 }
125 if (!E.BBRanges)
126 continue;
127 uint64_t TotalNumBlocks = 0;
128 bool EmitCallsiteEndOffsets =
129 FeatureOrErr->CallsiteEndOffsets || E.hasAnyCallsiteEndOffsets();
130 for (const BBAddrMapEntry::BBRangeEntry &BBR : *E.BBRanges) {
131 // Write the pointer-sized base address of the range.
132 if (AddressSize == 8)
133 CBA.write<uint64_t>(BBR.BaseAddress, Endian);
134 else
135 CBA.write<uint32_t>(static_cast<uint32_t>(BBR.BaseAddress), Endian);
136 // Write number of BBEntries (number of basic blocks in this basic block
137 // range). This is overridden by the 'NumBlocks' YAML field when
138 // specified.
139 uint64_t NumBlocks =
140 BBR.NumBlocks.value_or(BBR.BBEntries ? BBR.BBEntries->size() : 0);
141 CBA.writeULEB128(NumBlocks);
142 // Write all BBEntries in this BBRange.
143 if (!BBR.BBEntries || FeatureOrErr->OmitBBEntries)
144 continue;
145 for (const BBAddrMapEntry::BBEntry &BBE : *BBR.BBEntries) {
146 ++TotalNumBlocks;
147 if (E.Version > 1)
148 CBA.writeULEB128(BBE.ID);
150 if (EmitCallsiteEndOffsets) {
151 size_t NumCallsiteEndOffsets =
152 BBE.CallsiteEndOffsets ? BBE.CallsiteEndOffsets->size() : 0;
153 CBA.writeULEB128(NumCallsiteEndOffsets);
154 if (BBE.CallsiteEndOffsets) {
156 CBA.writeULEB128(Offset);
157 }
158 }
159 CBA.writeULEB128(BBE.Size);
160 CBA.writeULEB128(BBE.Metadata);
161 if (FeatureOrErr->BBHash || BBE.Hash.has_value()) {
162 uint64_t Hash =
163 BBE.Hash.has_value() ? BBE.Hash.value() : llvm::yaml::Hex64(0);
164 CBA.write<uint64_t>(Hash, Endian);
165 }
166 }
167 }
168 if (!PGOAnalyses)
169 continue;
170 const PGOAnalysisMapEntry &PGOEntry = PGOAnalyses->at(Idx);
171
172 if (PGOEntry.FuncEntryCount)
173 CBA.writeULEB128(*PGOEntry.FuncEntryCount);
174
175 if (!PGOEntry.PGOBBEntries)
176 continue;
177
178 const auto &PGOBBEntries = PGOEntry.PGOBBEntries.value();
179 if (TotalNumBlocks != PGOBBEntries.size()) {
180 WithColor::warning() << "PGOBBEntries must be the same length as "
181 "BBEntries in the BB address map.\n"
182 << "Mismatch on function with address: "
183 << E.getFunctionAddress();
184 continue;
185 }
186
187 for (const auto &PGOBBE : PGOBBEntries) {
188 if (PGOBBE.BBFreq)
189 CBA.writeULEB128(*PGOBBE.BBFreq);
190 if (FeatureOrErr->PostLinkCfg || PGOBBE.PostLinkBBFreq.has_value())
191 CBA.writeULEB128(PGOBBE.PostLinkBBFreq.value_or(0));
192 if (PGOBBE.Successors) {
193 CBA.writeULEB128(PGOBBE.Successors->size());
194 for (const auto &[ID, BrProb, PostLinkBrFreq] : *PGOBBE.Successors) {
195 CBA.writeULEB128(ID);
196 CBA.writeULEB128(BrProb);
197 if (FeatureOrErr->PostLinkCfg || PostLinkBrFreq.has_value())
198 CBA.writeULEB128(PostLinkBrFreq.value_or(0));
199 }
200 }
201 }
202 }
203}
204
206 ArrayRef<uint8_t> Content, llvm::endianness Endian, unsigned AddressSize,
207 std::optional<std::vector<BBAddrMapEntry>> &Entries,
208 std::optional<std::vector<PGOAnalysisMapEntry>> &PGOAnalyses) {
209 assert((AddressSize == 4 || AddressSize == 8) && "invalid address size");
210 DataExtractor Data(Content, Endian == llvm::endianness::little);
211
212 std::vector<BBAddrMapEntry> DecodedEntries;
213 bool HasAnyPGOAnalysisMapEntry = false;
214 std::vector<PGOAnalysisMapEntry> DecodedPGOAnalyses;
216 uint8_t Version = 0;
217 uint16_t Feature = 0;
218 uint64_t Address = 0;
219 while (Cur && Cur.tell() < Content.size()) {
220 Version = Data.getU8(Cur);
221 if (Cur && Version > 6)
222 return createStringError(
224 "invalid SHT_LLVM_BB_ADDR_MAP section version: " +
225 Twine(static_cast<int>(Version)));
226 Feature = Version < 5 ? Data.getU8(Cur) : Data.getU16(Cur);
227 if (!Cur)
228 break;
229 uint64_t NumBBRanges = 1;
230 uint64_t NumBlocks = 0;
231 uint32_t TotalNumBlocks = 0;
232 auto FeatureOrErr = llvm::object::BBAddrMap::Features::decode(Feature);
233 if (!FeatureOrErr)
234 return FeatureOrErr.takeError();
235 std::optional<llvm::yaml::Hex64> FuncGUID;
236 if (FeatureOrErr->FuncGUID)
237 FuncGUID = Data.getU64(Cur);
238 if (FeatureOrErr->MultiBBRange) {
239 NumBBRanges = Data.getULEB128(Cur);
240 } else {
241 Address = Data.getUnsigned(Cur, AddressSize);
242 NumBlocks = Data.getULEB128(Cur);
243 }
244 std::vector<BBAddrMapEntry::BBRangeEntry> BBRanges;
245 uint64_t BaseAddress = 0;
246 for (uint64_t BBRangeN = 0; Cur && BBRangeN != NumBBRanges; ++BBRangeN) {
247 if (FeatureOrErr->MultiBBRange) {
248 BaseAddress = Data.getUnsigned(Cur, AddressSize);
249 NumBlocks = Data.getULEB128(Cur);
250 } else {
251 BaseAddress = Address;
252 }
253
254 std::vector<BBAddrMapEntry::BBEntry> BBEntries;
255 // Read the specified number of BB entries, or until decoding fails.
256 for (uint64_t BlockIndex = 0; Cur && BlockIndex < NumBlocks;
257 ++BlockIndex) {
258 uint32_t ID = Version >= 2 ? Data.getULEB128(Cur) : BlockIndex;
259 uint64_t Offset = Data.getULEB128(Cur);
260 std::optional<std::vector<llvm::yaml::Hex64>> CallsiteEndOffsets;
261 if (FeatureOrErr->CallsiteEndOffsets) {
262 uint32_t NumCallsites = Data.getULEB128(Cur);
263 CallsiteEndOffsets = std::vector<llvm::yaml::Hex64>(NumCallsites, 0);
264 for (uint32_t CallsiteIndex = 0; Cur && CallsiteIndex < NumCallsites;
265 ++CallsiteIndex) {
266 (*CallsiteEndOffsets)[CallsiteIndex] = Data.getULEB128(Cur);
267 }
268 }
269 uint64_t Size = Data.getULEB128(Cur);
270 uint64_t Metadata = Data.getULEB128(Cur);
271 std::optional<llvm::yaml::Hex64> Hash;
272 if (FeatureOrErr->BBHash)
273 Hash = Data.getU64(Cur);
274 BBEntries.push_back(
275 {ID, Offset, Size, Metadata, std::move(CallsiteEndOffsets), Hash});
276 }
277 TotalNumBlocks += BBEntries.size();
278 BBRanges.push_back({BaseAddress, /*NumBlocks=*/{}, BBEntries});
279 }
280 DecodedEntries.push_back(
281 {Version, Feature, FuncGUID, /*NumBBRanges=*/{}, std::move(BBRanges)});
282
283 PGOAnalysisMapEntry &PGOAnalysis = DecodedPGOAnalyses.emplace_back();
284 if (FeatureOrErr->hasPGOAnalysis()) {
285 HasAnyPGOAnalysisMapEntry = true;
286
287 if (FeatureOrErr->FuncEntryCount)
288 PGOAnalysis.FuncEntryCount = Data.getULEB128(Cur);
289
290 if (FeatureOrErr->hasPGOAnalysisBBData()) {
291 auto &PGOBBEntries = PGOAnalysis.PGOBBEntries.emplace();
292 for (uint64_t BlockIndex = 0; Cur && BlockIndex < TotalNumBlocks;
293 ++BlockIndex) {
294 auto &PGOBBEntry = PGOBBEntries.emplace_back();
295 if (FeatureOrErr->BBFreq) {
296 PGOBBEntry.BBFreq = Data.getULEB128(Cur);
297 if (FeatureOrErr->PostLinkCfg)
298 PGOBBEntry.PostLinkBBFreq = Data.getULEB128(Cur);
299 if (!Cur)
300 break;
301 }
302
303 if (FeatureOrErr->BrProb) {
304 auto &SuccEntries = PGOBBEntry.Successors.emplace();
305 uint64_t SuccCount = Data.getULEB128(Cur);
306 for (uint64_t SuccIdx = 0; Cur && SuccIdx < SuccCount; ++SuccIdx) {
307 uint32_t ID = Data.getULEB128(Cur);
308 uint32_t BrProb = Data.getULEB128(Cur);
309 std::optional<uint32_t> PostLinkBrFreq;
310 if (FeatureOrErr->PostLinkCfg)
311 PostLinkBrFreq = Data.getULEB128(Cur);
312 SuccEntries.push_back({ID, BrProb, PostLinkBrFreq});
313 }
314 }
315 }
316 }
317 }
318 }
319
320 if (!Cur) {
321 consumeError(Cur.takeError());
322 return Error::success();
323 }
324 Entries = std::move(DecodedEntries);
325 if (HasAnyPGOAnalysisMapEntry)
326 PGOAnalyses = std::move(DecodedPGOAnalyses);
327 return Error::success();
328}
329
330} // end namespace BBAddrMapYAML
331} // end namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
This file declares the YAML representation of BB address maps (SHT_LLVM_BB_ADDR_MAP / ....
This file declares common types and utilities for basic-block address maps.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines ContiguousBlobAccumulator, the size-limited output buffer shared by the yaml2obj em...
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
A class representing a position in a DataExtractor, as well as any error encountered during extractio...
uint64_t tell() const
Return the current position of this Cursor.
Error takeError()
Return error contained inside this Cursor, if any.
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Root of the metadata hierarchy.
Definition Metadata.h:64
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
static LLVM_ABI raw_ostream & warning()
Convenience method for printing "warning: " to stderr.
Definition WithColor.cpp:86
void write(const char *Ptr, size_t Size)
void mapOptional(StringRef Key, T &Val)
Definition YAMLTraits.h:800
void * getContext() const
void mapRequired(StringRef Key, T &Val)
Definition YAMLTraits.h:790
LLVM_ABI Error decodePayload(ArrayRef< uint8_t > Content, llvm::endianness Endian, unsigned AddressSize, std::optional< std::vector< BBAddrMapEntry > > &Entries, std::optional< std::vector< PGOAnalysisMapEntry > > &PGOAnalyses)
Decodes the BBAddrMap payload in Content into Entries and PGOAnalyses.
LLVM_ABI void encodePayload(ArrayRef< BBAddrMapEntry > Entries, const std::vector< PGOAnalysisMapEntry > *PGOAnalyses, yaml::ContiguousBlobAccumulator &CBA, llvm::endianness Endian, unsigned AddressSize)
Encodes the BBAddrMap payload into CBA.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2570
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1321
@ invalid_argument
Definition Errc.h:56
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
endianness
Definition bit.h:71
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1106
std::optional< std::vector< llvm::yaml::Hex64 > > CallsiteEndOffsets
std::optional< llvm::yaml::Hex64 > Hash
std::optional< std::vector< BBEntry > > BBEntries
std::optional< uint64_t > FuncEntryCount
std::optional< std::vector< PGOBBEntry > > PGOBBEntries
static Expected< Features > decode(uint16_t Val)
Definition BBAddrMap.h:62
This class should be specialized by any type that needs to be converted to/from a YAML mapping.
Definition YAMLTraits.h:63