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 uint64_t NumBBRanges = 1;
228 uint64_t NumBlocks = 0;
229 uint32_t TotalNumBlocks = 0;
230 auto FeatureOrErr = llvm::object::BBAddrMap::Features::decode(Feature);
231 if (!FeatureOrErr)
232 return FeatureOrErr.takeError();
233 std::optional<llvm::yaml::Hex64> FuncGUID;
234 if (FeatureOrErr->FuncGUID)
235 FuncGUID = Data.getU64(Cur);
236 if (FeatureOrErr->MultiBBRange) {
237 NumBBRanges = Data.getULEB128(Cur);
238 } else {
239 Address = Data.getUnsigned(Cur, AddressSize);
240 NumBlocks = Data.getULEB128(Cur);
241 }
242 std::vector<BBAddrMapEntry::BBRangeEntry> BBRanges;
243 uint64_t BaseAddress = 0;
244 for (uint64_t BBRangeN = 0; Cur && BBRangeN != NumBBRanges; ++BBRangeN) {
245 if (FeatureOrErr->MultiBBRange) {
246 BaseAddress = Data.getUnsigned(Cur, AddressSize);
247 NumBlocks = Data.getULEB128(Cur);
248 } else {
249 BaseAddress = Address;
250 }
251
252 std::vector<BBAddrMapEntry::BBEntry> BBEntries;
253 // Read the specified number of BB entries, or until decoding fails.
254 for (uint64_t BlockIndex = 0; Cur && BlockIndex < NumBlocks;
255 ++BlockIndex) {
256 uint32_t ID = Version >= 2 ? Data.getULEB128(Cur) : BlockIndex;
257 uint64_t Offset = Data.getULEB128(Cur);
258 std::optional<std::vector<llvm::yaml::Hex64>> CallsiteEndOffsets;
259 if (FeatureOrErr->CallsiteEndOffsets) {
260 uint32_t NumCallsites = Data.getULEB128(Cur);
261 CallsiteEndOffsets = std::vector<llvm::yaml::Hex64>(NumCallsites, 0);
262 for (uint32_t CallsiteIndex = 0; Cur && CallsiteIndex < NumCallsites;
263 ++CallsiteIndex) {
264 (*CallsiteEndOffsets)[CallsiteIndex] = Data.getULEB128(Cur);
265 }
266 }
267 uint64_t Size = Data.getULEB128(Cur);
268 uint64_t Metadata = Data.getULEB128(Cur);
269 std::optional<llvm::yaml::Hex64> Hash;
270 if (FeatureOrErr->BBHash)
271 Hash = Data.getU64(Cur);
272 BBEntries.push_back(
273 {ID, Offset, Size, Metadata, std::move(CallsiteEndOffsets), Hash});
274 }
275 TotalNumBlocks += BBEntries.size();
276 BBRanges.push_back({BaseAddress, /*NumBlocks=*/{}, BBEntries});
277 }
278 DecodedEntries.push_back(
279 {Version, Feature, FuncGUID, /*NumBBRanges=*/{}, std::move(BBRanges)});
280
281 PGOAnalysisMapEntry &PGOAnalysis = DecodedPGOAnalyses.emplace_back();
282 if (FeatureOrErr->hasPGOAnalysis()) {
283 HasAnyPGOAnalysisMapEntry = true;
284
285 if (FeatureOrErr->FuncEntryCount)
286 PGOAnalysis.FuncEntryCount = Data.getULEB128(Cur);
287
288 if (FeatureOrErr->hasPGOAnalysisBBData()) {
289 auto &PGOBBEntries = PGOAnalysis.PGOBBEntries.emplace();
290 for (uint64_t BlockIndex = 0; Cur && BlockIndex < TotalNumBlocks;
291 ++BlockIndex) {
292 auto &PGOBBEntry = PGOBBEntries.emplace_back();
293 if (FeatureOrErr->BBFreq) {
294 PGOBBEntry.BBFreq = Data.getULEB128(Cur);
295 if (FeatureOrErr->PostLinkCfg)
296 PGOBBEntry.PostLinkBBFreq = Data.getULEB128(Cur);
297 if (!Cur)
298 break;
299 }
300
301 if (FeatureOrErr->BrProb) {
302 auto &SuccEntries = PGOBBEntry.Successors.emplace();
303 uint64_t SuccCount = Data.getULEB128(Cur);
304 for (uint64_t SuccIdx = 0; Cur && SuccIdx < SuccCount; ++SuccIdx) {
305 uint32_t ID = Data.getULEB128(Cur);
306 uint32_t BrProb = Data.getULEB128(Cur);
307 std::optional<uint32_t> PostLinkBrFreq;
308 if (FeatureOrErr->PostLinkCfg)
309 PostLinkBrFreq = Data.getULEB128(Cur);
310 SuccEntries.push_back({ID, BrProb, PostLinkBrFreq});
311 }
312 }
313 }
314 }
315 }
316 }
317
318 if (!Cur) {
319 consumeError(Cur.takeError());
320 return Error::success();
321 }
322 Entries = std::move(DecodedEntries);
323 if (HasAnyPGOAnalysisMapEntry)
324 PGOAnalyses = std::move(DecodedPGOAnalyses);
325 return Error::success();
326}
327
328} // end namespace BBAddrMapYAML
329} // 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