/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/ProfileData/InstrProfReader.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- InstrProfReader.cpp - Instrumented profiling reader ----------------===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | // |
10 | | // This file contains support for reading profiling data for clang's |
11 | | // instrumentation based PGO and coverage. |
12 | | // |
13 | | //===----------------------------------------------------------------------===// |
14 | | |
15 | | #include "llvm/ProfileData/InstrProfReader.h" |
16 | | #include "llvm/ADT/ArrayRef.h" |
17 | | #include "llvm/ADT/STLExtras.h" |
18 | | #include "llvm/ADT/StringRef.h" |
19 | | #include "llvm/IR/ProfileSummary.h" |
20 | | #include "llvm/ProfileData/InstrProf.h" |
21 | | #include "llvm/ProfileData/ProfileCommon.h" |
22 | | #include "llvm/Support/Endian.h" |
23 | | #include "llvm/Support/Error.h" |
24 | | #include "llvm/Support/ErrorOr.h" |
25 | | #include "llvm/Support/MemoryBuffer.h" |
26 | | #include "llvm/Support/SwapByteOrder.h" |
27 | | #include <algorithm> |
28 | | #include <cctype> |
29 | | #include <cstddef> |
30 | | #include <cstdint> |
31 | | #include <limits> |
32 | | #include <memory> |
33 | | #include <system_error> |
34 | | #include <utility> |
35 | | #include <vector> |
36 | | |
37 | | using namespace llvm; |
38 | | |
39 | | static Expected<std::unique_ptr<MemoryBuffer>> |
40 | 382 | setupMemoryBuffer(const Twine &Path) { |
41 | 382 | ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = |
42 | 382 | MemoryBuffer::getFileOrSTDIN(Path); |
43 | 382 | if (std::error_code EC = BufferOrErr.getError()) |
44 | 4 | return errorCodeToError(EC); |
45 | 378 | return std::move(BufferOrErr.get()); |
46 | 378 | } |
47 | | |
48 | 495 | static Error initializeReader(InstrProfReader &Reader) { |
49 | 495 | return Reader.readHeader(); |
50 | 495 | } |
51 | | |
52 | | Expected<std::unique_ptr<InstrProfReader>> |
53 | 192 | InstrProfReader::create(const Twine &Path) { |
54 | 192 | // Set up the buffer to read. |
55 | 192 | auto BufferOrError = setupMemoryBuffer(Path); |
56 | 192 | if (Error E = BufferOrError.takeError()) |
57 | 0 | return std::move(E); |
58 | 192 | return InstrProfReader::create(std::move(BufferOrError.get())); |
59 | 192 | } |
60 | | |
61 | | Expected<std::unique_ptr<InstrProfReader>> |
62 | 192 | InstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer) { |
63 | 192 | // Sanity check the buffer. |
64 | 192 | if (Buffer->getBufferSize() > std::numeric_limits<unsigned>::max()) |
65 | 0 | return make_error<InstrProfError>(instrprof_error::too_large); |
66 | 192 | |
67 | 192 | if (192 Buffer->getBufferSize() == 0192 ) |
68 | 3 | return make_error<InstrProfError>(instrprof_error::empty_raw_profile); |
69 | 189 | |
70 | 189 | std::unique_ptr<InstrProfReader> Result; |
71 | 189 | // Create the reader. |
72 | 189 | if (IndexedInstrProfReader::hasFormat(*Buffer)) |
73 | 51 | Result.reset(new IndexedInstrProfReader(std::move(Buffer))); |
74 | 138 | else if (138 RawInstrProfReader64::hasFormat(*Buffer)138 ) |
75 | 8 | Result.reset(new RawInstrProfReader64(std::move(Buffer))); |
76 | 130 | else if (130 RawInstrProfReader32::hasFormat(*Buffer)130 ) |
77 | 2 | Result.reset(new RawInstrProfReader32(std::move(Buffer))); |
78 | 128 | else if (128 TextInstrProfReader::hasFormat(*Buffer)128 ) |
79 | 127 | Result.reset(new TextInstrProfReader(std::move(Buffer))); |
80 | 128 | else |
81 | 1 | return make_error<InstrProfError>(instrprof_error::unrecognized_format); |
82 | 188 | |
83 | 188 | // Initialize the reader and return the result. |
84 | 188 | if (Error 188 E188 = initializeReader(*Result)) |
85 | 2 | return std::move(E); |
86 | 186 | |
87 | 186 | return std::move(Result); |
88 | 186 | } |
89 | | |
90 | | Expected<std::unique_ptr<IndexedInstrProfReader>> |
91 | 190 | IndexedInstrProfReader::create(const Twine &Path) { |
92 | 190 | // Set up the buffer to read. |
93 | 190 | auto BufferOrError = setupMemoryBuffer(Path); |
94 | 190 | if (Error E = BufferOrError.takeError()) |
95 | 4 | return std::move(E); |
96 | 186 | return IndexedInstrProfReader::create(std::move(BufferOrError.get())); |
97 | 186 | } |
98 | | |
99 | | Expected<std::unique_ptr<IndexedInstrProfReader>> |
100 | 307 | IndexedInstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer) { |
101 | 307 | // Sanity check the buffer. |
102 | 307 | if (Buffer->getBufferSize() > std::numeric_limits<unsigned>::max()) |
103 | 0 | return make_error<InstrProfError>(instrprof_error::too_large); |
104 | 307 | |
105 | 307 | // Create the reader. |
106 | 307 | if (307 !IndexedInstrProfReader::hasFormat(*Buffer)307 ) |
107 | 0 | return make_error<InstrProfError>(instrprof_error::bad_magic); |
108 | 307 | auto Result = llvm::make_unique<IndexedInstrProfReader>(std::move(Buffer)); |
109 | 307 | |
110 | 307 | // Initialize the reader and return the result. |
111 | 307 | if (Error E = initializeReader(*Result)) |
112 | 0 | return std::move(E); |
113 | 307 | |
114 | 307 | return std::move(Result); |
115 | 307 | } |
116 | | |
117 | 609 | void InstrProfIterator::Increment() { |
118 | 609 | if (auto E609 = Reader->readNextRecord(Record)) { |
119 | 191 | // Handle errors in the reader. |
120 | 191 | InstrProfError::take(std::move(E)); |
121 | 191 | *this = InstrProfIterator(); |
122 | 191 | } |
123 | 609 | } |
124 | | |
125 | 128 | bool TextInstrProfReader::hasFormat(const MemoryBuffer &Buffer) { |
126 | 128 | // Verify that this really looks like plain ASCII text by checking a |
127 | 128 | // 'reasonable' number of characters (up to profile magic size). |
128 | 128 | size_t count = std::min(Buffer.getBufferSize(), sizeof(uint64_t)); |
129 | 128 | StringRef buffer = Buffer.getBufferStart(); |
130 | 128 | return count == 0 || |
131 | 128 | std::all_of(buffer.begin(), buffer.begin() + count, |
132 | 1.00k | [](char c) { return ::isprint(c) || 1.00k ::isspace(c)161 ; }); |
133 | 128 | } |
134 | | |
135 | | // Read the profile variant flag from the header: ":FE" means this is a FE |
136 | | // generated profile. ":IR" means this is an IR level profile. Other strings |
137 | | // with a leading ':' will be reported an error format. |
138 | 127 | Error TextInstrProfReader::readHeader() { |
139 | 127 | Symtab.reset(new InstrProfSymtab()); |
140 | 127 | bool IsIRInstr = false; |
141 | 127 | if (!Line->startswith(":")127 ) { |
142 | 100 | IsIRLevelProfile = false; |
143 | 100 | return success(); |
144 | 100 | } |
145 | 27 | StringRef Str = (Line)->substr(1); |
146 | 27 | if (Str.equals_lower("ir")) |
147 | 26 | IsIRInstr = true; |
148 | 1 | else if (1 Str.equals_lower("fe")1 ) |
149 | 1 | IsIRInstr = false; |
150 | 1 | else |
151 | 0 | return error(instrprof_error::bad_header); |
152 | 27 | |
153 | 27 | ++Line; |
154 | 27 | IsIRLevelProfile = IsIRInstr; |
155 | 27 | return success(); |
156 | 27 | } |
157 | | |
158 | | Error |
159 | 240 | TextInstrProfReader::readValueProfileData(InstrProfRecord &Record) { |
160 | 240 | |
161 | 240 | #define CHECK_LINE_END(Line) \ |
162 | 175 | if (175 Line.is_at_end()157 ) \ |
163 | 175 | return error(instrprof_error::truncated); |
164 | 240 | #define READ_NUM(Str, Dst) \ |
165 | 210 | if (210 (Str).getAsInteger(10, (Dst))210 ) \ |
166 | 210 | return error(instrprof_error::malformed); |
167 | 240 | #define VP_READ_ADVANCE(Val) \ |
168 | 91 | CHECK_LINE_END73 (Line); \ |
169 | 72 | uint32_t Val; \ |
170 | 72 | READ_NUM72 ((*Line), (Val)); \ |
171 | 72 | Line++; |
172 | 240 | |
173 | 240 | if (Line.is_at_end()) |
174 | 110 | return success(); |
175 | 130 | |
176 | 130 | uint32_t NumValueKinds; |
177 | 130 | if (Line->getAsInteger(10, NumValueKinds)130 ) { |
178 | 117 | // No value profile data |
179 | 117 | return success(); |
180 | 117 | } |
181 | 13 | if (13 NumValueKinds == 0 || 13 NumValueKinds > IPVK_Last + 113 ) |
182 | 0 | return error(instrprof_error::malformed); |
183 | 13 | Line++; |
184 | 13 | |
185 | 28 | for (uint32_t VK = 0; VK < NumValueKinds28 ; VK++15 ) { |
186 | 18 | VP_READ_ADVANCE18 (ValueKind); |
187 | 18 | if (ValueKind > IPVK_Last) |
188 | 0 | return error(instrprof_error::malformed); |
189 | 18 | VP_READ_ADVANCE18 (NumValueSites); |
190 | 18 | if (!NumValueSites) |
191 | 0 | continue; |
192 | 18 | |
193 | 18 | Record.reserveSites(VK, NumValueSites); |
194 | 52 | for (uint32_t S = 0; S < NumValueSites52 ; S++34 ) { |
195 | 37 | VP_READ_ADVANCE37 (NumValueData); |
196 | 72 | |
197 | 72 | std::vector<InstrProfValueData> CurrentValues; |
198 | 118 | for (uint32_t V = 0; V < NumValueData118 ; V++82 ) { |
199 | 84 | CHECK_LINE_END84 (Line); |
200 | 84 | std::pair<StringRef, StringRef> VD = Line->rsplit(':'); |
201 | 84 | uint64_t TakenCount, Value; |
202 | 84 | if (ValueKind == IPVK_IndirectCallTarget84 ) { |
203 | 30 | if (Error E = Symtab->addFuncName(VD.first)) |
204 | 0 | return E; |
205 | 30 | Value = IndexedInstrProf::ComputeHash(VD.first); |
206 | 84 | } else { |
207 | 54 | READ_NUM54 (VD.first, Value); |
208 | 54 | } |
209 | 84 | READ_NUM84 (VD.second, TakenCount)84 ; |
210 | 82 | CurrentValues.push_back({Value, TakenCount}); |
211 | 82 | Line++; |
212 | 82 | } |
213 | 34 | Record.addValueData(ValueKind, S, CurrentValues.data(), NumValueData, |
214 | 34 | nullptr); |
215 | 34 | } |
216 | 18 | } |
217 | 10 | return success(); |
218 | 240 | |
219 | 240 | #undef CHECK_LINE_END |
220 | 240 | #undef READ_NUM |
221 | 240 | #undef VP_READ_ADVANCE |
222 | 240 | } |
223 | | |
224 | 365 | Error TextInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) { |
225 | 365 | // Skip empty lines and comments. |
226 | 365 | while (!Line.is_at_end() && 365 (Line->empty() || 246 Line->startswith("#")246 )) |
227 | 0 | ++Line; |
228 | 365 | // If we hit EOF while looking for a name, we're done. |
229 | 365 | if (Line.is_at_end()365 ) { |
230 | 119 | Symtab->finalizeSymtab(); |
231 | 119 | return error(instrprof_error::eof); |
232 | 119 | } |
233 | 246 | |
234 | 246 | // Read the function name. |
235 | 246 | Record.Name = *Line++; |
236 | 246 | if (Error E = Symtab->addFuncName(Record.Name)) |
237 | 0 | return E; |
238 | 246 | |
239 | 246 | // Read the function hash. |
240 | 246 | if (246 Line.is_at_end()246 ) |
241 | 0 | return error(instrprof_error::truncated); |
242 | 246 | if (246 (Line++)->getAsInteger(0, Record.Hash)246 ) |
243 | 2 | return error(instrprof_error::malformed); |
244 | 244 | |
245 | 244 | // Read the number of counters. |
246 | 244 | uint64_t NumCounters; |
247 | 244 | if (Line.is_at_end()) |
248 | 0 | return error(instrprof_error::truncated); |
249 | 244 | if (244 (Line++)->getAsInteger(10, NumCounters)244 ) |
250 | 0 | return error(instrprof_error::malformed); |
251 | 244 | if (244 NumCounters == 0244 ) |
252 | 1 | return error(instrprof_error::malformed); |
253 | 243 | |
254 | 243 | // Read each counter and fill our internal storage with the values. |
255 | 243 | Record.Clear(); |
256 | 243 | Record.Counts.reserve(NumCounters); |
257 | 874 | for (uint64_t I = 0; I < NumCounters874 ; ++I631 ) { |
258 | 633 | if (Line.is_at_end()) |
259 | 0 | return error(instrprof_error::truncated); |
260 | 633 | uint64_t Count; |
261 | 633 | if ((Line++)->getAsInteger(10, Count)) |
262 | 2 | return error(instrprof_error::malformed); |
263 | 631 | Record.Counts.push_back(Count); |
264 | 631 | } |
265 | 243 | |
266 | 243 | // Check if value profile data exists and read it if so. |
267 | 241 | if (Error 241 E241 = readValueProfileData(Record)) |
268 | 3 | return E; |
269 | 238 | |
270 | 238 | // This is needed to avoid two pass parsing because llvm-profdata |
271 | 238 | // does dumping while reading. |
272 | 238 | Symtab->finalizeSymtab(); |
273 | 238 | return success(); |
274 | 238 | } |
275 | | |
276 | | template <class IntPtrT> |
277 | 278 | bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) { |
278 | 278 | if (DataBuffer.getBufferSize() < sizeof(uint64_t)) |
279 | 6 | return false; |
280 | 272 | uint64_t Magic = |
281 | 272 | *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart()); |
282 | 272 | return RawInstrProf::getMagic<IntPtrT>() == Magic || |
283 | 258 | sys::getSwappedBytes(RawInstrProf::getMagic<IntPtrT>()) == Magic; |
284 | 278 | } llvm::RawInstrProfReader<unsigned int>::hasFormat(llvm::MemoryBuffer const&) Line | Count | Source | 277 | 132 | bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) { | 278 | 132 | if (DataBuffer.getBufferSize() < sizeof(uint64_t)) | 279 | 3 | return false; | 280 | 129 | uint64_t Magic = | 281 | 129 | *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart()); | 282 | 129 | return RawInstrProf::getMagic<IntPtrT>() == Magic || | 283 | 127 | sys::getSwappedBytes(RawInstrProf::getMagic<IntPtrT>()) == Magic; | 284 | 132 | } |
llvm::RawInstrProfReader<unsigned long long>::hasFormat(llvm::MemoryBuffer const&) Line | Count | Source | 277 | 146 | bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) { | 278 | 146 | if (DataBuffer.getBufferSize() < sizeof(uint64_t)) | 279 | 3 | return false; | 280 | 143 | uint64_t Magic = | 281 | 143 | *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart()); | 282 | 143 | return RawInstrProf::getMagic<IntPtrT>() == Magic || | 283 | 131 | sys::getSwappedBytes(RawInstrProf::getMagic<IntPtrT>()) == Magic; | 284 | 146 | } |
|
285 | | |
286 | | template <class IntPtrT> |
287 | 10 | Error RawInstrProfReader<IntPtrT>::readHeader() { |
288 | 10 | if (!hasFormat(*DataBuffer)) |
289 | 0 | return error(instrprof_error::bad_magic); |
290 | 10 | if (10 DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header)10 ) |
291 | 2 | return error(instrprof_error::bad_header); |
292 | 8 | auto *Header = reinterpret_cast<const RawInstrProf::Header *>( |
293 | 8 | DataBuffer->getBufferStart()); |
294 | 8 | ShouldSwapBytes = Header->Magic != RawInstrProf::getMagic<IntPtrT>(); |
295 | 8 | return readHeader(*Header); |
296 | 8 | } llvm::RawInstrProfReader<unsigned long long>::readHeader() Line | Count | Source | 287 | 8 | Error RawInstrProfReader<IntPtrT>::readHeader() { | 288 | 8 | if (!hasFormat(*DataBuffer)) | 289 | 0 | return error(instrprof_error::bad_magic); | 290 | 8 | if (8 DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header)8 ) | 291 | 2 | return error(instrprof_error::bad_header); | 292 | 6 | auto *Header = reinterpret_cast<const RawInstrProf::Header *>( | 293 | 6 | DataBuffer->getBufferStart()); | 294 | 6 | ShouldSwapBytes = Header->Magic != RawInstrProf::getMagic<IntPtrT>(); | 295 | 6 | return readHeader(*Header); | 296 | 6 | } |
llvm::RawInstrProfReader<unsigned int>::readHeader() Line | Count | Source | 287 | 2 | Error RawInstrProfReader<IntPtrT>::readHeader() { | 288 | 2 | if (!hasFormat(*DataBuffer)) | 289 | 0 | return error(instrprof_error::bad_magic); | 290 | 2 | if (2 DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header)2 ) | 291 | 0 | return error(instrprof_error::bad_header); | 292 | 2 | auto *Header = reinterpret_cast<const RawInstrProf::Header *>( | 293 | 2 | DataBuffer->getBufferStart()); | 294 | 2 | ShouldSwapBytes = Header->Magic != RawInstrProf::getMagic<IntPtrT>(); | 295 | 2 | return readHeader(*Header); | 296 | 2 | } |
|
297 | | |
298 | | template <class IntPtrT> |
299 | 9 | Error RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) { |
300 | 9 | const char *End = DataBuffer->getBufferEnd(); |
301 | 9 | // Skip zero padding between profiles. |
302 | 9 | while (CurrentPos != End && 9 *CurrentPos == 01 ) |
303 | 0 | ++CurrentPos; |
304 | 9 | // If there's nothing left, we're done. |
305 | 9 | if (CurrentPos == End) |
306 | 8 | return make_error<InstrProfError>(instrprof_error::eof); |
307 | 1 | // If there isn't enough space for another header, this is probably just |
308 | 1 | // garbage at the end of the file. |
309 | 1 | if (1 CurrentPos + sizeof(RawInstrProf::Header) > End1 ) |
310 | 0 | return make_error<InstrProfError>(instrprof_error::malformed); |
311 | 1 | // The writer ensures each profile is padded to start at an aligned address. |
312 | 1 | if (1 reinterpret_cast<size_t>(CurrentPos) % alignof(uint64_t)1 ) |
313 | 0 | return make_error<InstrProfError>(instrprof_error::malformed); |
314 | 1 | // The magic should have the same byte order as in the previous header. |
315 | 1 | uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos); |
316 | 1 | if (Magic != swap(RawInstrProf::getMagic<IntPtrT>())) |
317 | 0 | return make_error<InstrProfError>(instrprof_error::bad_magic); |
318 | 1 | |
319 | 1 | // There's another profile to read, so we need to process the header. |
320 | 1 | auto *Header = reinterpret_cast<const RawInstrProf::Header *>(CurrentPos); |
321 | 1 | return readHeader(*Header); |
322 | 1 | } llvm::RawInstrProfReader<unsigned long long>::readNextHeader(char const*) Line | Count | Source | 299 | 7 | Error RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) { | 300 | 7 | const char *End = DataBuffer->getBufferEnd(); | 301 | 7 | // Skip zero padding between profiles. | 302 | 7 | while (CurrentPos != End && 7 *CurrentPos == 01 ) | 303 | 0 | ++CurrentPos; | 304 | 7 | // If there's nothing left, we're done. | 305 | 7 | if (CurrentPos == End) | 306 | 6 | return make_error<InstrProfError>(instrprof_error::eof); | 307 | 1 | // If there isn't enough space for another header, this is probably just | 308 | 1 | // garbage at the end of the file. | 309 | 1 | if (1 CurrentPos + sizeof(RawInstrProf::Header) > End1 ) | 310 | 0 | return make_error<InstrProfError>(instrprof_error::malformed); | 311 | 1 | // The writer ensures each profile is padded to start at an aligned address. | 312 | 1 | if (1 reinterpret_cast<size_t>(CurrentPos) % alignof(uint64_t)1 ) | 313 | 0 | return make_error<InstrProfError>(instrprof_error::malformed); | 314 | 1 | // The magic should have the same byte order as in the previous header. | 315 | 1 | uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos); | 316 | 1 | if (Magic != swap(RawInstrProf::getMagic<IntPtrT>())) | 317 | 0 | return make_error<InstrProfError>(instrprof_error::bad_magic); | 318 | 1 | | 319 | 1 | // There's another profile to read, so we need to process the header. | 320 | 1 | auto *Header = reinterpret_cast<const RawInstrProf::Header *>(CurrentPos); | 321 | 1 | return readHeader(*Header); | 322 | 1 | } |
llvm::RawInstrProfReader<unsigned int>::readNextHeader(char const*) Line | Count | Source | 299 | 2 | Error RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) { | 300 | 2 | const char *End = DataBuffer->getBufferEnd(); | 301 | 2 | // Skip zero padding between profiles. | 302 | 2 | while (CurrentPos != End && 2 *CurrentPos == 00 ) | 303 | 0 | ++CurrentPos; | 304 | 2 | // If there's nothing left, we're done. | 305 | 2 | if (CurrentPos == End) | 306 | 2 | return make_error<InstrProfError>(instrprof_error::eof); | 307 | 0 | // If there isn't enough space for another header, this is probably just | 308 | 0 | // garbage at the end of the file. | 309 | 0 | if (0 CurrentPos + sizeof(RawInstrProf::Header) > End0 ) | 310 | 0 | return make_error<InstrProfError>(instrprof_error::malformed); | 311 | 0 | // The writer ensures each profile is padded to start at an aligned address. | 312 | 0 | if (0 reinterpret_cast<size_t>(CurrentPos) % alignof(uint64_t)0 ) | 313 | 0 | return make_error<InstrProfError>(instrprof_error::malformed); | 314 | 0 | // The magic should have the same byte order as in the previous header. | 315 | 0 | uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos); | 316 | 0 | if (Magic != swap(RawInstrProf::getMagic<IntPtrT>())) | 317 | 0 | return make_error<InstrProfError>(instrprof_error::bad_magic); | 318 | 0 |
| 319 | 0 | // There's another profile to read, so we need to process the header. | 320 | 0 | auto *Header = reinterpret_cast<const RawInstrProf::Header *>(CurrentPos); | 321 | 0 | return readHeader(*Header); | 322 | 0 | } |
|
323 | | |
324 | | template <class IntPtrT> |
325 | 9 | Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) { |
326 | 9 | if (Error E = Symtab.create(StringRef(NamesStart, NamesSize))) |
327 | 0 | return error(std::move(E)); |
328 | 55 | for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; 9 I != DataEnd55 ; ++I46 ) { |
329 | 46 | const IntPtrT FPtr = swap(I->FunctionPointer); |
330 | 46 | if (!FPtr) |
331 | 10 | continue; |
332 | 36 | Symtab.mapAddress(FPtr, I->NameRef); |
333 | 36 | } |
334 | 9 | Symtab.finalizeSymtab(); |
335 | 9 | return success(); |
336 | 9 | } llvm::RawInstrProfReader<unsigned long long>::createSymtab(llvm::InstrProfSymtab&) Line | Count | Source | 325 | 7 | Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) { | 326 | 7 | if (Error E = Symtab.create(StringRef(NamesStart, NamesSize))) | 327 | 0 | return error(std::move(E)); | 328 | 49 | for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; 7 I != DataEnd49 ; ++I42 ) { | 329 | 42 | const IntPtrT FPtr = swap(I->FunctionPointer); | 330 | 42 | if (!FPtr) | 331 | 6 | continue; | 332 | 36 | Symtab.mapAddress(FPtr, I->NameRef); | 333 | 36 | } | 334 | 7 | Symtab.finalizeSymtab(); | 335 | 7 | return success(); | 336 | 7 | } |
llvm::RawInstrProfReader<unsigned int>::createSymtab(llvm::InstrProfSymtab&) Line | Count | Source | 325 | 2 | Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) { | 326 | 2 | if (Error E = Symtab.create(StringRef(NamesStart, NamesSize))) | 327 | 0 | return error(std::move(E)); | 328 | 6 | for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; 2 I != DataEnd6 ; ++I4 ) { | 329 | 4 | const IntPtrT FPtr = swap(I->FunctionPointer); | 330 | 4 | if (!FPtr) | 331 | 4 | continue; | 332 | 0 | Symtab.mapAddress(FPtr, I->NameRef); | 333 | 0 | } | 334 | 2 | Symtab.finalizeSymtab(); | 335 | 2 | return success(); | 336 | 2 | } |
|
337 | | |
338 | | template <class IntPtrT> |
339 | | Error RawInstrProfReader<IntPtrT>::readHeader( |
340 | 9 | const RawInstrProf::Header &Header) { |
341 | 9 | Version = swap(Header.Version); |
342 | 9 | if (GET_VERSION9 (Version) != RawInstrProf::Version9 ) |
343 | 0 | return error(instrprof_error::unsupported_version); |
344 | 9 | |
345 | 9 | CountersDelta = swap(Header.CountersDelta); |
346 | 9 | NamesDelta = swap(Header.NamesDelta); |
347 | 9 | auto DataSize = swap(Header.DataSize); |
348 | 9 | auto CountersSize = swap(Header.CountersSize); |
349 | 9 | NamesSize = swap(Header.NamesSize); |
350 | 9 | ValueKindLast = swap(Header.ValueKindLast); |
351 | 9 | |
352 | 9 | auto DataSizeInBytes = DataSize * sizeof(RawInstrProf::ProfileData<IntPtrT>); |
353 | 9 | auto PaddingSize = getNumPaddingBytes(NamesSize); |
354 | 9 | |
355 | 9 | ptrdiff_t DataOffset = sizeof(RawInstrProf::Header); |
356 | 9 | ptrdiff_t CountersOffset = DataOffset + DataSizeInBytes; |
357 | 9 | ptrdiff_t NamesOffset = CountersOffset + sizeof(uint64_t) * CountersSize; |
358 | 9 | ptrdiff_t ValueDataOffset = NamesOffset + NamesSize + PaddingSize; |
359 | 9 | |
360 | 9 | auto *Start = reinterpret_cast<const char *>(&Header); |
361 | 9 | if (Start + ValueDataOffset > DataBuffer->getBufferEnd()) |
362 | 0 | return error(instrprof_error::bad_header); |
363 | 9 | |
364 | 9 | Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>( |
365 | 9 | Start + DataOffset); |
366 | 9 | DataEnd = Data + DataSize; |
367 | 9 | CountersStart = reinterpret_cast<const uint64_t *>(Start + CountersOffset); |
368 | 9 | NamesStart = Start + NamesOffset; |
369 | 9 | ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset); |
370 | 9 | |
371 | 9 | std::unique_ptr<InstrProfSymtab> NewSymtab = make_unique<InstrProfSymtab>(); |
372 | 9 | if (Error E = createSymtab(*NewSymtab.get())) |
373 | 0 | return E; |
374 | 9 | |
375 | 9 | Symtab = std::move(NewSymtab); |
376 | 9 | return success(); |
377 | 9 | } llvm::RawInstrProfReader<unsigned int>::readHeader(llvm::RawInstrProf::Header const&) Line | Count | Source | 340 | 2 | const RawInstrProf::Header &Header) { | 341 | 2 | Version = swap(Header.Version); | 342 | 2 | if (GET_VERSION2 (Version) != RawInstrProf::Version2 ) | 343 | 0 | return error(instrprof_error::unsupported_version); | 344 | 2 | | 345 | 2 | CountersDelta = swap(Header.CountersDelta); | 346 | 2 | NamesDelta = swap(Header.NamesDelta); | 347 | 2 | auto DataSize = swap(Header.DataSize); | 348 | 2 | auto CountersSize = swap(Header.CountersSize); | 349 | 2 | NamesSize = swap(Header.NamesSize); | 350 | 2 | ValueKindLast = swap(Header.ValueKindLast); | 351 | 2 | | 352 | 2 | auto DataSizeInBytes = DataSize * sizeof(RawInstrProf::ProfileData<IntPtrT>); | 353 | 2 | auto PaddingSize = getNumPaddingBytes(NamesSize); | 354 | 2 | | 355 | 2 | ptrdiff_t DataOffset = sizeof(RawInstrProf::Header); | 356 | 2 | ptrdiff_t CountersOffset = DataOffset + DataSizeInBytes; | 357 | 2 | ptrdiff_t NamesOffset = CountersOffset + sizeof(uint64_t) * CountersSize; | 358 | 2 | ptrdiff_t ValueDataOffset = NamesOffset + NamesSize + PaddingSize; | 359 | 2 | | 360 | 2 | auto *Start = reinterpret_cast<const char *>(&Header); | 361 | 2 | if (Start + ValueDataOffset > DataBuffer->getBufferEnd()) | 362 | 0 | return error(instrprof_error::bad_header); | 363 | 2 | | 364 | 2 | Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>( | 365 | 2 | Start + DataOffset); | 366 | 2 | DataEnd = Data + DataSize; | 367 | 2 | CountersStart = reinterpret_cast<const uint64_t *>(Start + CountersOffset); | 368 | 2 | NamesStart = Start + NamesOffset; | 369 | 2 | ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset); | 370 | 2 | | 371 | 2 | std::unique_ptr<InstrProfSymtab> NewSymtab = make_unique<InstrProfSymtab>(); | 372 | 2 | if (Error E = createSymtab(*NewSymtab.get())) | 373 | 0 | return E; | 374 | 2 | | 375 | 2 | Symtab = std::move(NewSymtab); | 376 | 2 | return success(); | 377 | 2 | } |
llvm::RawInstrProfReader<unsigned long long>::readHeader(llvm::RawInstrProf::Header const&) Line | Count | Source | 340 | 7 | const RawInstrProf::Header &Header) { | 341 | 7 | Version = swap(Header.Version); | 342 | 7 | if (GET_VERSION7 (Version) != RawInstrProf::Version7 ) | 343 | 0 | return error(instrprof_error::unsupported_version); | 344 | 7 | | 345 | 7 | CountersDelta = swap(Header.CountersDelta); | 346 | 7 | NamesDelta = swap(Header.NamesDelta); | 347 | 7 | auto DataSize = swap(Header.DataSize); | 348 | 7 | auto CountersSize = swap(Header.CountersSize); | 349 | 7 | NamesSize = swap(Header.NamesSize); | 350 | 7 | ValueKindLast = swap(Header.ValueKindLast); | 351 | 7 | | 352 | 7 | auto DataSizeInBytes = DataSize * sizeof(RawInstrProf::ProfileData<IntPtrT>); | 353 | 7 | auto PaddingSize = getNumPaddingBytes(NamesSize); | 354 | 7 | | 355 | 7 | ptrdiff_t DataOffset = sizeof(RawInstrProf::Header); | 356 | 7 | ptrdiff_t CountersOffset = DataOffset + DataSizeInBytes; | 357 | 7 | ptrdiff_t NamesOffset = CountersOffset + sizeof(uint64_t) * CountersSize; | 358 | 7 | ptrdiff_t ValueDataOffset = NamesOffset + NamesSize + PaddingSize; | 359 | 7 | | 360 | 7 | auto *Start = reinterpret_cast<const char *>(&Header); | 361 | 7 | if (Start + ValueDataOffset > DataBuffer->getBufferEnd()) | 362 | 0 | return error(instrprof_error::bad_header); | 363 | 7 | | 364 | 7 | Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>( | 365 | 7 | Start + DataOffset); | 366 | 7 | DataEnd = Data + DataSize; | 367 | 7 | CountersStart = reinterpret_cast<const uint64_t *>(Start + CountersOffset); | 368 | 7 | NamesStart = Start + NamesOffset; | 369 | 7 | ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset); | 370 | 7 | | 371 | 7 | std::unique_ptr<InstrProfSymtab> NewSymtab = make_unique<InstrProfSymtab>(); | 372 | 7 | if (Error E = createSymtab(*NewSymtab.get())) | 373 | 0 | return E; | 374 | 7 | | 375 | 7 | Symtab = std::move(NewSymtab); | 376 | 7 | return success(); | 377 | 7 | } |
|
378 | | |
379 | | template <class IntPtrT> |
380 | 46 | Error RawInstrProfReader<IntPtrT>::readName(NamedInstrProfRecord &Record) { |
381 | 46 | Record.Name = getName(Data->NameRef); |
382 | 46 | return success(); |
383 | 46 | } llvm::RawInstrProfReader<unsigned int>::readName(llvm::NamedInstrProfRecord&) Line | Count | Source | 380 | 4 | Error RawInstrProfReader<IntPtrT>::readName(NamedInstrProfRecord &Record) { | 381 | 4 | Record.Name = getName(Data->NameRef); | 382 | 4 | return success(); | 383 | 4 | } |
llvm::RawInstrProfReader<unsigned long long>::readName(llvm::NamedInstrProfRecord&) Line | Count | Source | 380 | 42 | Error RawInstrProfReader<IntPtrT>::readName(NamedInstrProfRecord &Record) { | 381 | 42 | Record.Name = getName(Data->NameRef); | 382 | 42 | return success(); | 383 | 42 | } |
|
384 | | |
385 | | template <class IntPtrT> |
386 | 46 | Error RawInstrProfReader<IntPtrT>::readFuncHash(NamedInstrProfRecord &Record) { |
387 | 46 | Record.Hash = swap(Data->FuncHash); |
388 | 46 | return success(); |
389 | 46 | } llvm::RawInstrProfReader<unsigned long long>::readFuncHash(llvm::NamedInstrProfRecord&) Line | Count | Source | 386 | 42 | Error RawInstrProfReader<IntPtrT>::readFuncHash(NamedInstrProfRecord &Record) { | 387 | 42 | Record.Hash = swap(Data->FuncHash); | 388 | 42 | return success(); | 389 | 42 | } |
llvm::RawInstrProfReader<unsigned int>::readFuncHash(llvm::NamedInstrProfRecord&) Line | Count | Source | 386 | 4 | Error RawInstrProfReader<IntPtrT>::readFuncHash(NamedInstrProfRecord &Record) { | 387 | 4 | Record.Hash = swap(Data->FuncHash); | 388 | 4 | return success(); | 389 | 4 | } |
|
390 | | |
391 | | template <class IntPtrT> |
392 | | Error RawInstrProfReader<IntPtrT>::readRawCounts( |
393 | 46 | InstrProfRecord &Record) { |
394 | 46 | uint32_t NumCounters = swap(Data->NumCounters); |
395 | 46 | IntPtrT CounterPtr = Data->CounterPtr; |
396 | 46 | if (NumCounters == 0) |
397 | 0 | return error(instrprof_error::malformed); |
398 | 46 | |
399 | 46 | auto RawCounts = makeArrayRef(getCounter(CounterPtr), NumCounters); |
400 | 46 | auto *NamesStartAsCounter = reinterpret_cast<const uint64_t *>(NamesStart); |
401 | 46 | |
402 | 46 | // Check bounds. |
403 | 46 | if (RawCounts.data() < CountersStart || |
404 | 46 | RawCounts.data() + RawCounts.size() > NamesStartAsCounter) |
405 | 0 | return error(instrprof_error::malformed); |
406 | 46 | |
407 | 46 | if (46 ShouldSwapBytes46 ) { |
408 | 4 | Record.Counts.clear(); |
409 | 4 | Record.Counts.reserve(RawCounts.size()); |
410 | 4 | for (uint64_t Count : RawCounts) |
411 | 6 | Record.Counts.push_back(swap(Count)); |
412 | 4 | } else |
413 | 42 | Record.Counts = RawCounts; |
414 | 46 | |
415 | 46 | return success(); |
416 | 46 | } llvm::RawInstrProfReader<unsigned long long>::readRawCounts(llvm::InstrProfRecord&) Line | Count | Source | 393 | 42 | InstrProfRecord &Record) { | 394 | 42 | uint32_t NumCounters = swap(Data->NumCounters); | 395 | 42 | IntPtrT CounterPtr = Data->CounterPtr; | 396 | 42 | if (NumCounters == 0) | 397 | 0 | return error(instrprof_error::malformed); | 398 | 42 | | 399 | 42 | auto RawCounts = makeArrayRef(getCounter(CounterPtr), NumCounters); | 400 | 42 | auto *NamesStartAsCounter = reinterpret_cast<const uint64_t *>(NamesStart); | 401 | 42 | | 402 | 42 | // Check bounds. | 403 | 42 | if (RawCounts.data() < CountersStart || | 404 | 42 | RawCounts.data() + RawCounts.size() > NamesStartAsCounter) | 405 | 0 | return error(instrprof_error::malformed); | 406 | 42 | | 407 | 42 | if (42 ShouldSwapBytes42 ) { | 408 | 2 | Record.Counts.clear(); | 409 | 2 | Record.Counts.reserve(RawCounts.size()); | 410 | 2 | for (uint64_t Count : RawCounts) | 411 | 3 | Record.Counts.push_back(swap(Count)); | 412 | 2 | } else | 413 | 40 | Record.Counts = RawCounts; | 414 | 42 | | 415 | 42 | return success(); | 416 | 42 | } |
llvm::RawInstrProfReader<unsigned int>::readRawCounts(llvm::InstrProfRecord&) Line | Count | Source | 393 | 4 | InstrProfRecord &Record) { | 394 | 4 | uint32_t NumCounters = swap(Data->NumCounters); | 395 | 4 | IntPtrT CounterPtr = Data->CounterPtr; | 396 | 4 | if (NumCounters == 0) | 397 | 0 | return error(instrprof_error::malformed); | 398 | 4 | | 399 | 4 | auto RawCounts = makeArrayRef(getCounter(CounterPtr), NumCounters); | 400 | 4 | auto *NamesStartAsCounter = reinterpret_cast<const uint64_t *>(NamesStart); | 401 | 4 | | 402 | 4 | // Check bounds. | 403 | 4 | if (RawCounts.data() < CountersStart || | 404 | 4 | RawCounts.data() + RawCounts.size() > NamesStartAsCounter) | 405 | 0 | return error(instrprof_error::malformed); | 406 | 4 | | 407 | 4 | if (4 ShouldSwapBytes4 ) { | 408 | 2 | Record.Counts.clear(); | 409 | 2 | Record.Counts.reserve(RawCounts.size()); | 410 | 2 | for (uint64_t Count : RawCounts) | 411 | 3 | Record.Counts.push_back(swap(Count)); | 412 | 2 | } else | 413 | 2 | Record.Counts = RawCounts; | 414 | 4 | | 415 | 4 | return success(); | 416 | 4 | } |
|
417 | | |
418 | | template <class IntPtrT> |
419 | | Error RawInstrProfReader<IntPtrT>::readValueProfilingData( |
420 | 46 | InstrProfRecord &Record) { |
421 | 46 | Record.clearValueData(); |
422 | 46 | CurValueDataSize = 0; |
423 | 46 | // Need to match the logic in value profile dumper code in compiler-rt: |
424 | 46 | uint32_t NumValueKinds = 0; |
425 | 138 | for (uint32_t I = 0; I < IPVK_Last + 1138 ; I++92 ) |
426 | 92 | NumValueKinds += (Data->NumValueSites[I] != 0); |
427 | 46 | |
428 | 46 | if (!NumValueKinds) |
429 | 46 | return success(); |
430 | 0 |
|
431 | 0 | Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr = |
432 | 0 | ValueProfData::getValueProfData( |
433 | 0 | ValueDataStart, (const unsigned char *)DataBuffer->getBufferEnd(), |
434 | 0 | getDataEndianness()); |
435 | 0 |
|
436 | 0 | if (Error E = VDataPtrOrErr.takeError()) |
437 | 0 | return E; |
438 | 0 |
|
439 | 0 | // Note that besides deserialization, this also performs the conversion for |
440 | 0 | // indirect call targets. The function pointers from the raw profile are |
441 | 0 | // remapped into function name hashes. |
442 | 0 | VDataPtrOrErr.get()->deserializeTo(Record, &Symtab->getAddrHashMap()); |
443 | 0 | CurValueDataSize = VDataPtrOrErr.get()->getSize(); |
444 | 0 | return success(); |
445 | 0 | } llvm::RawInstrProfReader<unsigned int>::readValueProfilingData(llvm::InstrProfRecord&) Line | Count | Source | 420 | 4 | InstrProfRecord &Record) { | 421 | 4 | Record.clearValueData(); | 422 | 4 | CurValueDataSize = 0; | 423 | 4 | // Need to match the logic in value profile dumper code in compiler-rt: | 424 | 4 | uint32_t NumValueKinds = 0; | 425 | 12 | for (uint32_t I = 0; I < IPVK_Last + 112 ; I++8 ) | 426 | 8 | NumValueKinds += (Data->NumValueSites[I] != 0); | 427 | 4 | | 428 | 4 | if (!NumValueKinds) | 429 | 4 | return success(); | 430 | 0 |
| 431 | 0 | Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr = | 432 | 0 | ValueProfData::getValueProfData( | 433 | 0 | ValueDataStart, (const unsigned char *)DataBuffer->getBufferEnd(), | 434 | 0 | getDataEndianness()); | 435 | 0 |
| 436 | 0 | if (Error E = VDataPtrOrErr.takeError()) | 437 | 0 | return E; | 438 | 0 |
| 439 | 0 | // Note that besides deserialization, this also performs the conversion for | 440 | 0 | // indirect call targets. The function pointers from the raw profile are | 441 | 0 | // remapped into function name hashes. | 442 | 0 | VDataPtrOrErr.get()->deserializeTo(Record, &Symtab->getAddrHashMap()); | 443 | 0 | CurValueDataSize = VDataPtrOrErr.get()->getSize(); | 444 | 0 | return success(); | 445 | 0 | } |
llvm::RawInstrProfReader<unsigned long long>::readValueProfilingData(llvm::InstrProfRecord&) Line | Count | Source | 420 | 42 | InstrProfRecord &Record) { | 421 | 42 | Record.clearValueData(); | 422 | 42 | CurValueDataSize = 0; | 423 | 42 | // Need to match the logic in value profile dumper code in compiler-rt: | 424 | 42 | uint32_t NumValueKinds = 0; | 425 | 126 | for (uint32_t I = 0; I < IPVK_Last + 1126 ; I++84 ) | 426 | 84 | NumValueKinds += (Data->NumValueSites[I] != 0); | 427 | 42 | | 428 | 42 | if (!NumValueKinds) | 429 | 42 | return success(); | 430 | 0 |
| 431 | 0 | Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr = | 432 | 0 | ValueProfData::getValueProfData( | 433 | 0 | ValueDataStart, (const unsigned char *)DataBuffer->getBufferEnd(), | 434 | 0 | getDataEndianness()); | 435 | 0 |
| 436 | 0 | if (Error E = VDataPtrOrErr.takeError()) | 437 | 0 | return E; | 438 | 0 |
| 439 | 0 | // Note that besides deserialization, this also performs the conversion for | 440 | 0 | // indirect call targets. The function pointers from the raw profile are | 441 | 0 | // remapped into function name hashes. | 442 | 0 | VDataPtrOrErr.get()->deserializeTo(Record, &Symtab->getAddrHashMap()); | 443 | 0 | CurValueDataSize = VDataPtrOrErr.get()->getSize(); | 444 | 0 | return success(); | 445 | 0 | } |
|
446 | | |
447 | | template <class IntPtrT> |
448 | 54 | Error RawInstrProfReader<IntPtrT>::readNextRecord(NamedInstrProfRecord &Record) { |
449 | 54 | if (atEnd()) |
450 | 54 | // At this point, ValueDataStart field points to the next header. |
451 | 9 | if (Error 9 E9 = readNextHeader(getNextHeaderPos())) |
452 | 8 | return E; |
453 | 46 | |
454 | 46 | // Read name ad set it in Record. |
455 | 46 | if (Error 46 E46 = readName(Record)) |
456 | 0 | return E; |
457 | 46 | |
458 | 46 | // Read FuncHash and set it in Record. |
459 | 46 | if (Error 46 E46 = readFuncHash(Record)) |
460 | 0 | return E; |
461 | 46 | |
462 | 46 | // Read raw counts and set Record. |
463 | 46 | if (Error 46 E46 = readRawCounts(Record)) |
464 | 0 | return E; |
465 | 46 | |
466 | 46 | // Read value data and set Record. |
467 | 46 | if (Error 46 E46 = readValueProfilingData(Record)) |
468 | 0 | return E; |
469 | 46 | |
470 | 46 | // Iterate. |
471 | 46 | advanceData(); |
472 | 46 | return success(); |
473 | 46 | } llvm::RawInstrProfReader<unsigned int>::readNextRecord(llvm::NamedInstrProfRecord&) Line | Count | Source | 448 | 6 | Error RawInstrProfReader<IntPtrT>::readNextRecord(NamedInstrProfRecord &Record) { | 449 | 6 | if (atEnd()) | 450 | 6 | // At this point, ValueDataStart field points to the next header. | 451 | 2 | if (Error 2 E2 = readNextHeader(getNextHeaderPos())) | 452 | 2 | return E; | 453 | 4 | | 454 | 4 | // Read name ad set it in Record. | 455 | 4 | if (Error 4 E4 = readName(Record)) | 456 | 0 | return E; | 457 | 4 | | 458 | 4 | // Read FuncHash and set it in Record. | 459 | 4 | if (Error 4 E4 = readFuncHash(Record)) | 460 | 0 | return E; | 461 | 4 | | 462 | 4 | // Read raw counts and set Record. | 463 | 4 | if (Error 4 E4 = readRawCounts(Record)) | 464 | 0 | return E; | 465 | 4 | | 466 | 4 | // Read value data and set Record. | 467 | 4 | if (Error 4 E4 = readValueProfilingData(Record)) | 468 | 0 | return E; | 469 | 4 | | 470 | 4 | // Iterate. | 471 | 4 | advanceData(); | 472 | 4 | return success(); | 473 | 4 | } |
llvm::RawInstrProfReader<unsigned long long>::readNextRecord(llvm::NamedInstrProfRecord&) Line | Count | Source | 448 | 48 | Error RawInstrProfReader<IntPtrT>::readNextRecord(NamedInstrProfRecord &Record) { | 449 | 48 | if (atEnd()) | 450 | 48 | // At this point, ValueDataStart field points to the next header. | 451 | 7 | if (Error 7 E7 = readNextHeader(getNextHeaderPos())) | 452 | 6 | return E; | 453 | 42 | | 454 | 42 | // Read name ad set it in Record. | 455 | 42 | if (Error 42 E42 = readName(Record)) | 456 | 0 | return E; | 457 | 42 | | 458 | 42 | // Read FuncHash and set it in Record. | 459 | 42 | if (Error 42 E42 = readFuncHash(Record)) | 460 | 0 | return E; | 461 | 42 | | 462 | 42 | // Read raw counts and set Record. | 463 | 42 | if (Error 42 E42 = readRawCounts(Record)) | 464 | 0 | return E; | 465 | 42 | | 466 | 42 | // Read value data and set Record. | 467 | 42 | if (Error 42 E42 = readValueProfilingData(Record)) | 468 | 0 | return E; | 469 | 42 | | 470 | 42 | // Iterate. | 471 | 42 | advanceData(); | 472 | 42 | return success(); | 473 | 42 | } |
|
474 | | |
475 | | namespace llvm { |
476 | | |
477 | | template class RawInstrProfReader<uint32_t>; |
478 | | template class RawInstrProfReader<uint64_t>; |
479 | | |
480 | | } // end namespace llvm |
481 | | |
482 | | InstrProfLookupTrait::hash_value_type |
483 | 507 | InstrProfLookupTrait::ComputeHash(StringRef K) { |
484 | 507 | return IndexedInstrProf::ComputeHash(HashType, K); |
485 | 507 | } |
486 | | |
487 | | using data_type = InstrProfLookupTrait::data_type; |
488 | | using offset_type = InstrProfLookupTrait::offset_type; |
489 | | |
490 | | bool InstrProfLookupTrait::readValueProfilingData( |
491 | 516 | const unsigned char *&D, const unsigned char *const End) { |
492 | 516 | Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr = |
493 | 516 | ValueProfData::getValueProfData(D, End, ValueProfDataEndianness); |
494 | 516 | |
495 | 516 | if (VDataPtrOrErr.takeError()) |
496 | 0 | return false; |
497 | 516 | |
498 | 516 | VDataPtrOrErr.get()->deserializeTo(DataBuffer.back(), nullptr); |
499 | 516 | D += VDataPtrOrErr.get()->TotalSize; |
500 | 516 | |
501 | 516 | return true; |
502 | 516 | } |
503 | | |
504 | | data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D, |
505 | 593 | offset_type N) { |
506 | 593 | using namespace support; |
507 | 593 | |
508 | 593 | // Check if the data is corrupt. If so, don't try to read it. |
509 | 593 | if (N % sizeof(uint64_t)) |
510 | 0 | return data_type(); |
511 | 593 | |
512 | 593 | DataBuffer.clear(); |
513 | 593 | std::vector<uint64_t> CounterBuffer; |
514 | 593 | |
515 | 593 | const unsigned char *End = D + N; |
516 | 1.20k | while (D < End1.20k ) { |
517 | 613 | // Read hash. |
518 | 613 | if (D + sizeof(uint64_t) >= End) |
519 | 0 | return data_type(); |
520 | 613 | uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D); |
521 | 613 | |
522 | 613 | // Initialize number of counters for GET_VERSION(FormatVersion) == 1. |
523 | 613 | uint64_t CountsSize = N / sizeof(uint64_t) - 1; |
524 | 613 | // If format version is different then read the number of counters. |
525 | 613 | if (GET_VERSION613 (FormatVersion) != IndexedInstrProf::ProfVersion::Version1613 ) { |
526 | 589 | if (D + sizeof(uint64_t) > End) |
527 | 0 | return data_type(); |
528 | 589 | CountsSize = endian::readNext<uint64_t, little, unaligned>(D); |
529 | 589 | } |
530 | 613 | // Read counter values. |
531 | 613 | if (613 D + CountsSize * sizeof(uint64_t) > End613 ) |
532 | 0 | return data_type(); |
533 | 613 | |
534 | 613 | CounterBuffer.clear(); |
535 | 613 | CounterBuffer.reserve(CountsSize); |
536 | 2.72k | for (uint64_t J = 0; J < CountsSize2.72k ; ++J2.10k ) |
537 | 2.10k | CounterBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D)); |
538 | 613 | |
539 | 613 | DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer)); |
540 | 613 | |
541 | 613 | // Read value profiling data. |
542 | 613 | if (GET_VERSION613 (FormatVersion) > IndexedInstrProf::ProfVersion::Version2 && |
543 | 613 | !readValueProfilingData(D, End)516 ) { |
544 | 0 | DataBuffer.clear(); |
545 | 0 | return data_type(); |
546 | 0 | } |
547 | 613 | } |
548 | 593 | return DataBuffer; |
549 | 593 | } |
550 | | |
551 | | template <typename HashTableImpl> |
552 | | Error InstrProfReaderIndex<HashTableImpl>::getRecords( |
553 | 507 | StringRef FuncName, ArrayRef<NamedInstrProfRecord> &Data) { |
554 | 507 | auto Iter = HashTable->find(FuncName); |
555 | 507 | if (Iter == HashTable->end()) |
556 | 48 | return make_error<InstrProfError>(instrprof_error::unknown_function); |
557 | 459 | |
558 | 459 | Data = (*Iter); |
559 | 459 | if (Data.empty()) |
560 | 0 | return make_error<InstrProfError>(instrprof_error::malformed); |
561 | 459 | |
562 | 459 | return Error::success(); |
563 | 459 | } |
564 | | |
565 | | template <typename HashTableImpl> |
566 | | Error InstrProfReaderIndex<HashTableImpl>::getRecords( |
567 | 190 | ArrayRef<NamedInstrProfRecord> &Data) { |
568 | 190 | if (atEnd()) |
569 | 56 | return make_error<InstrProfError>(instrprof_error::eof); |
570 | 134 | |
571 | 134 | Data = *RecordIterator; |
572 | 134 | |
573 | 134 | if (Data.empty()) |
574 | 0 | return make_error<InstrProfError>(instrprof_error::malformed); |
575 | 134 | |
576 | 134 | return Error::success(); |
577 | 134 | } |
578 | | |
579 | | template <typename HashTableImpl> |
580 | | InstrProfReaderIndex<HashTableImpl>::InstrProfReaderIndex( |
581 | | const unsigned char *Buckets, const unsigned char *const Payload, |
582 | | const unsigned char *const Base, IndexedInstrProf::HashT HashType, |
583 | 358 | uint64_t Version) { |
584 | 358 | FormatVersion = Version; |
585 | 358 | HashTable.reset(HashTableImpl::Create( |
586 | 358 | Buckets, Payload, Base, |
587 | 358 | typename HashTableImpl::InfoType(HashType, Version))); |
588 | 358 | RecordIterator = HashTable->data_begin(); |
589 | 358 | } |
590 | | |
591 | 496 | bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) { |
592 | 496 | using namespace support; |
593 | 496 | |
594 | 496 | if (DataBuffer.getBufferSize() < 8) |
595 | 3 | return false; |
596 | 493 | uint64_t Magic = |
597 | 493 | endian::read<uint64_t, little, aligned>(DataBuffer.getBufferStart()); |
598 | 493 | // Verify that it's magical. |
599 | 493 | return Magic == IndexedInstrProf::Magic; |
600 | 493 | } |
601 | | |
602 | | const unsigned char * |
603 | | IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version, |
604 | 358 | const unsigned char *Cur) { |
605 | 358 | using namespace IndexedInstrProf; |
606 | 358 | using namespace support; |
607 | 358 | |
608 | 358 | if (Version >= IndexedInstrProf::Version4358 ) { |
609 | 321 | const IndexedInstrProf::Summary *SummaryInLE = |
610 | 321 | reinterpret_cast<const IndexedInstrProf::Summary *>(Cur); |
611 | 321 | uint64_t NFields = |
612 | 321 | endian::byte_swap<uint64_t, little>(SummaryInLE->NumSummaryFields); |
613 | 321 | uint64_t NEntries = |
614 | 321 | endian::byte_swap<uint64_t, little>(SummaryInLE->NumCutoffEntries); |
615 | 321 | uint32_t SummarySize = |
616 | 321 | IndexedInstrProf::Summary::getSize(NFields, NEntries); |
617 | 321 | std::unique_ptr<IndexedInstrProf::Summary> SummaryData = |
618 | 321 | IndexedInstrProf::allocSummary(SummarySize); |
619 | 321 | |
620 | 321 | const uint64_t *Src = reinterpret_cast<const uint64_t *>(SummaryInLE); |
621 | 321 | uint64_t *Dst = reinterpret_cast<uint64_t *>(SummaryData.get()); |
622 | 20.2k | for (unsigned I = 0; I < SummarySize / sizeof(uint64_t)20.2k ; I++19.9k ) |
623 | 19.9k | Dst[I] = endian::byte_swap<uint64_t, little>(Src[I]); |
624 | 321 | |
625 | 321 | SummaryEntryVector DetailedSummary; |
626 | 6.09k | for (unsigned I = 0; I < SummaryData->NumCutoffEntries6.09k ; I++5.77k ) { |
627 | 5.77k | const IndexedInstrProf::Summary::Entry &Ent = SummaryData->getEntry(I); |
628 | 5.77k | DetailedSummary.emplace_back((uint32_t)Ent.Cutoff, Ent.MinBlockCount, |
629 | 5.77k | Ent.NumBlocks); |
630 | 5.77k | } |
631 | 321 | // initialize InstrProfSummary using the SummaryData from disk. |
632 | 321 | this->Summary = llvm::make_unique<ProfileSummary>( |
633 | 321 | ProfileSummary::PSK_Instr, DetailedSummary, |
634 | 321 | SummaryData->get(Summary::TotalBlockCount), |
635 | 321 | SummaryData->get(Summary::MaxBlockCount), |
636 | 321 | SummaryData->get(Summary::MaxInternalBlockCount), |
637 | 321 | SummaryData->get(Summary::MaxFunctionCount), |
638 | 321 | SummaryData->get(Summary::TotalNumBlocks), |
639 | 321 | SummaryData->get(Summary::TotalNumFunctions)); |
640 | 321 | return Cur + SummarySize; |
641 | 0 | } else { |
642 | 37 | // For older version of profile data, we need to compute on the fly: |
643 | 37 | using namespace IndexedInstrProf; |
644 | 37 | |
645 | 37 | InstrProfSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs); |
646 | 37 | // FIXME: This only computes an empty summary. Need to call addRecord for |
647 | 37 | // all NamedInstrProfRecords to get the correct summary. |
648 | 37 | this->Summary = Builder.getSummary(); |
649 | 37 | return Cur; |
650 | 37 | } |
651 | 0 | } |
652 | | |
653 | 358 | Error IndexedInstrProfReader::readHeader() { |
654 | 358 | using namespace support; |
655 | 358 | |
656 | 358 | const unsigned char *Start = |
657 | 358 | (const unsigned char *)DataBuffer->getBufferStart(); |
658 | 358 | const unsigned char *Cur = Start; |
659 | 358 | if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24) |
660 | 0 | return error(instrprof_error::truncated); |
661 | 358 | |
662 | 358 | auto *Header = reinterpret_cast<const IndexedInstrProf::Header *>(Cur); |
663 | 358 | Cur += sizeof(IndexedInstrProf::Header); |
664 | 358 | |
665 | 358 | // Check the magic number. |
666 | 358 | uint64_t Magic = endian::byte_swap<uint64_t, little>(Header->Magic); |
667 | 358 | if (Magic != IndexedInstrProf::Magic) |
668 | 0 | return error(instrprof_error::bad_magic); |
669 | 358 | |
670 | 358 | // Read the version. |
671 | 358 | uint64_t FormatVersion = endian::byte_swap<uint64_t, little>(Header->Version); |
672 | 358 | if (GET_VERSION358 (FormatVersion) > |
673 | 358 | IndexedInstrProf::ProfVersion::CurrentVersion) |
674 | 0 | return error(instrprof_error::unsupported_version); |
675 | 358 | |
676 | 358 | Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur); |
677 | 358 | |
678 | 358 | // Read the hash type and start offset. |
679 | 358 | IndexedInstrProf::HashT HashType = static_cast<IndexedInstrProf::HashT>( |
680 | 358 | endian::byte_swap<uint64_t, little>(Header->HashType)); |
681 | 358 | if (HashType > IndexedInstrProf::HashT::Last) |
682 | 0 | return error(instrprof_error::unsupported_hash_type); |
683 | 358 | |
684 | 358 | uint64_t HashOffset = endian::byte_swap<uint64_t, little>(Header->HashOffset); |
685 | 358 | |
686 | 358 | // The rest of the file is an on disk hash table. |
687 | 358 | InstrProfReaderIndexBase *IndexPtr = nullptr; |
688 | 358 | IndexPtr = new InstrProfReaderIndex<OnDiskHashTableImplV3>( |
689 | 358 | Start + HashOffset, Cur, Start, HashType, FormatVersion); |
690 | 358 | Index.reset(IndexPtr); |
691 | 358 | return success(); |
692 | 358 | } |
693 | | |
694 | 5 | InstrProfSymtab &IndexedInstrProfReader::getSymtab() { |
695 | 5 | if (Symtab.get()) |
696 | 3 | return *Symtab.get(); |
697 | 2 | |
698 | 2 | std::unique_ptr<InstrProfSymtab> NewSymtab = make_unique<InstrProfSymtab>(); |
699 | 2 | if (Error E2 = Index->populateSymtab(*NewSymtab.get())) { |
700 | 0 | consumeError(error(InstrProfError::take(std::move(E)))); |
701 | 0 | } |
702 | 5 | |
703 | 5 | Symtab = std::move(NewSymtab); |
704 | 5 | return *Symtab.get(); |
705 | 5 | } |
706 | | |
707 | | Expected<InstrProfRecord> |
708 | | IndexedInstrProfReader::getInstrProfRecord(StringRef FuncName, |
709 | 507 | uint64_t FuncHash) { |
710 | 507 | ArrayRef<NamedInstrProfRecord> Data; |
711 | 507 | Error Err = Index->getRecords(FuncName, Data); |
712 | 507 | if (Err) |
713 | 48 | return std::move(Err); |
714 | 459 | // Found it. Look for counters with the right hash. |
715 | 481 | for (unsigned I = 0, E = Data.size(); 459 I < E481 ; ++I22 ) { |
716 | 471 | // Check for a match and fill the vector if there is one. |
717 | 471 | if (Data[I].Hash == FuncHash471 ) { |
718 | 449 | return std::move(Data[I]); |
719 | 449 | } |
720 | 471 | } |
721 | 10 | return error(instrprof_error::hash_mismatch); |
722 | 507 | } |
723 | | |
724 | | Error IndexedInstrProfReader::getFunctionCounts(StringRef FuncName, |
725 | | uint64_t FuncHash, |
726 | 326 | std::vector<uint64_t> &Counts) { |
727 | 326 | Expected<InstrProfRecord> Record = getInstrProfRecord(FuncName, FuncHash); |
728 | 326 | if (Error E = Record.takeError()) |
729 | 36 | return error(std::move(E)); |
730 | 290 | |
731 | 290 | Counts = Record.get().Counts; |
732 | 290 | return success(); |
733 | 290 | } |
734 | | |
735 | 190 | Error IndexedInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) { |
736 | 190 | static unsigned RecordIndex = 0; |
737 | 190 | |
738 | 190 | ArrayRef<NamedInstrProfRecord> Data; |
739 | 190 | |
740 | 190 | Error E = Index->getRecords(Data); |
741 | 190 | if (E) |
742 | 56 | return error(std::move(E)); |
743 | 134 | |
744 | 134 | Record = Data[RecordIndex++]; |
745 | 134 | if (RecordIndex >= Data.size()134 ) { |
746 | 133 | Index->advanceToNextKey(); |
747 | 133 | RecordIndex = 0; |
748 | 133 | } |
749 | 190 | return success(); |
750 | 190 | } |