File: | lib/ProfileData/Coverage/CoverageMappingReader.cpp |
Warning: | line 81, column 14 The left operand of '>' is a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- CoverageMappingReader.cpp - Code coverage mapping 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 coverage mapping data for | |||
11 | // instrumentation based coverage. | |||
12 | // | |||
13 | //===----------------------------------------------------------------------===// | |||
14 | ||||
15 | #include "llvm/ProfileData/Coverage/CoverageMappingReader.h" | |||
16 | #include "llvm/ADT/ArrayRef.h" | |||
17 | #include "llvm/ADT/DenseMap.h" | |||
18 | #include "llvm/ADT/STLExtras.h" | |||
19 | #include "llvm/ADT/SmallVector.h" | |||
20 | #include "llvm/ADT/StringRef.h" | |||
21 | #include "llvm/ADT/Triple.h" | |||
22 | #include "llvm/Object/Binary.h" | |||
23 | #include "llvm/Object/Error.h" | |||
24 | #include "llvm/Object/MachOUniversal.h" | |||
25 | #include "llvm/Object/ObjectFile.h" | |||
26 | #include "llvm/ProfileData/InstrProf.h" | |||
27 | #include "llvm/Support/Casting.h" | |||
28 | #include "llvm/Support/Debug.h" | |||
29 | #include "llvm/Support/Endian.h" | |||
30 | #include "llvm/Support/Error.h" | |||
31 | #include "llvm/Support/ErrorHandling.h" | |||
32 | #include "llvm/Support/LEB128.h" | |||
33 | #include "llvm/Support/MathExtras.h" | |||
34 | #include "llvm/Support/raw_ostream.h" | |||
35 | #include <vector> | |||
36 | ||||
37 | using namespace llvm; | |||
38 | using namespace coverage; | |||
39 | using namespace object; | |||
40 | ||||
41 | #define DEBUG_TYPE"coverage-mapping" "coverage-mapping" | |||
42 | ||||
43 | void CoverageMappingIterator::increment() { | |||
44 | if (ReadErr != coveragemap_error::success) | |||
45 | return; | |||
46 | ||||
47 | // Check if all the records were read or if an error occurred while reading | |||
48 | // the next record. | |||
49 | if (auto E = Reader->readNextRecord(Record)) | |||
50 | handleAllErrors(std::move(E), [&](const CoverageMapError &CME) { | |||
51 | if (CME.get() == coveragemap_error::eof) | |||
52 | *this = CoverageMappingIterator(); | |||
53 | else | |||
54 | ReadErr = CME.get(); | |||
55 | }); | |||
56 | } | |||
57 | ||||
58 | Error RawCoverageReader::readULEB128(uint64_t &Result) { | |||
59 | if (Data.empty()) | |||
60 | return make_error<CoverageMapError>(coveragemap_error::truncated); | |||
61 | unsigned N = 0; | |||
62 | Result = decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N); | |||
63 | if (N > Data.size()) | |||
64 | return make_error<CoverageMapError>(coveragemap_error::malformed); | |||
65 | Data = Data.substr(N); | |||
66 | return Error::success(); | |||
67 | } | |||
68 | ||||
69 | Error RawCoverageReader::readIntMax(uint64_t &Result, uint64_t MaxPlus1) { | |||
70 | if (auto Err = readULEB128(Result)) | |||
71 | return Err; | |||
72 | if (Result >= MaxPlus1) | |||
73 | return make_error<CoverageMapError>(coveragemap_error::malformed); | |||
74 | return Error::success(); | |||
75 | } | |||
76 | ||||
77 | Error RawCoverageReader::readSize(uint64_t &Result) { | |||
78 | if (auto Err = readULEB128(Result)) | |||
79 | return Err; | |||
80 | // Sanity check the number. | |||
81 | if (Result > Data.size()) | |||
| ||||
82 | return make_error<CoverageMapError>(coveragemap_error::malformed); | |||
83 | return Error::success(); | |||
84 | } | |||
85 | ||||
86 | Error RawCoverageReader::readString(StringRef &Result) { | |||
87 | uint64_t Length; | |||
| ||||
88 | if (auto Err = readSize(Length)) | |||
89 | return Err; | |||
90 | Result = Data.substr(0, Length); | |||
91 | Data = Data.substr(Length); | |||
92 | return Error::success(); | |||
93 | } | |||
94 | ||||
95 | Error RawCoverageFilenamesReader::read() { | |||
96 | uint64_t NumFilenames; | |||
97 | if (auto Err = readSize(NumFilenames)) | |||
98 | return Err; | |||
99 | for (size_t I = 0; I < NumFilenames; ++I) { | |||
100 | StringRef Filename; | |||
101 | if (auto Err = readString(Filename)) | |||
102 | return Err; | |||
103 | Filenames.push_back(Filename); | |||
104 | } | |||
105 | return Error::success(); | |||
106 | } | |||
107 | ||||
108 | Error RawCoverageMappingReader::decodeCounter(unsigned Value, Counter &C) { | |||
109 | auto Tag = Value & Counter::EncodingTagMask; | |||
110 | switch (Tag) { | |||
111 | case Counter::Zero: | |||
112 | C = Counter::getZero(); | |||
113 | return Error::success(); | |||
114 | case Counter::CounterValueReference: | |||
115 | C = Counter::getCounter(Value >> Counter::EncodingTagBits); | |||
116 | return Error::success(); | |||
117 | default: | |||
118 | break; | |||
119 | } | |||
120 | Tag -= Counter::Expression; | |||
121 | switch (Tag) { | |||
122 | case CounterExpression::Subtract: | |||
123 | case CounterExpression::Add: { | |||
124 | auto ID = Value >> Counter::EncodingTagBits; | |||
125 | if (ID >= Expressions.size()) | |||
126 | return make_error<CoverageMapError>(coveragemap_error::malformed); | |||
127 | Expressions[ID].Kind = CounterExpression::ExprKind(Tag); | |||
128 | C = Counter::getExpression(ID); | |||
129 | break; | |||
130 | } | |||
131 | default: | |||
132 | return make_error<CoverageMapError>(coveragemap_error::malformed); | |||
133 | } | |||
134 | return Error::success(); | |||
135 | } | |||
136 | ||||
137 | Error RawCoverageMappingReader::readCounter(Counter &C) { | |||
138 | uint64_t EncodedCounter; | |||
139 | if (auto Err = | |||
140 | readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max())) | |||
141 | return Err; | |||
142 | if (auto Err = decodeCounter(EncodedCounter, C)) | |||
143 | return Err; | |||
144 | return Error::success(); | |||
145 | } | |||
146 | ||||
147 | static const unsigned EncodingExpansionRegionBit = 1 | |||
148 | << Counter::EncodingTagBits; | |||
149 | ||||
150 | /// \brief Read the sub-array of regions for the given inferred file id. | |||
151 | /// \param NumFileIDs the number of file ids that are defined for this | |||
152 | /// function. | |||
153 | Error RawCoverageMappingReader::readMappingRegionsSubArray( | |||
154 | std::vector<CounterMappingRegion> &MappingRegions, unsigned InferredFileID, | |||
155 | size_t NumFileIDs) { | |||
156 | uint64_t NumRegions; | |||
157 | if (auto Err = readSize(NumRegions)) | |||
158 | return Err; | |||
159 | unsigned LineStart = 0; | |||
160 | for (size_t I = 0; I < NumRegions; ++I) { | |||
161 | Counter C; | |||
162 | CounterMappingRegion::RegionKind Kind = CounterMappingRegion::CodeRegion; | |||
163 | ||||
164 | // Read the combined counter + region kind. | |||
165 | uint64_t EncodedCounterAndRegion; | |||
166 | if (auto Err = readIntMax(EncodedCounterAndRegion, | |||
167 | std::numeric_limits<unsigned>::max())) | |||
168 | return Err; | |||
169 | unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask; | |||
170 | uint64_t ExpandedFileID = 0; | |||
171 | if (Tag != Counter::Zero) { | |||
172 | if (auto Err = decodeCounter(EncodedCounterAndRegion, C)) | |||
173 | return Err; | |||
174 | } else { | |||
175 | // Is it an expansion region? | |||
176 | if (EncodedCounterAndRegion & EncodingExpansionRegionBit) { | |||
177 | Kind = CounterMappingRegion::ExpansionRegion; | |||
178 | ExpandedFileID = EncodedCounterAndRegion >> | |||
179 | Counter::EncodingCounterTagAndExpansionRegionTagBits; | |||
180 | if (ExpandedFileID >= NumFileIDs) | |||
181 | return make_error<CoverageMapError>(coveragemap_error::malformed); | |||
182 | } else { | |||
183 | switch (EncodedCounterAndRegion >> | |||
184 | Counter::EncodingCounterTagAndExpansionRegionTagBits) { | |||
185 | case CounterMappingRegion::CodeRegion: | |||
186 | // Don't do anything when we have a code region with a zero counter. | |||
187 | break; | |||
188 | case CounterMappingRegion::SkippedRegion: | |||
189 | Kind = CounterMappingRegion::SkippedRegion; | |||
190 | break; | |||
191 | default: | |||
192 | return make_error<CoverageMapError>(coveragemap_error::malformed); | |||
193 | } | |||
194 | } | |||
195 | } | |||
196 | ||||
197 | // Read the source range. | |||
198 | uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd; | |||
199 | if (auto Err = | |||
200 | readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max())) | |||
201 | return Err; | |||
202 | if (auto Err = readULEB128(ColumnStart)) | |||
203 | return Err; | |||
204 | if (ColumnStart > std::numeric_limits<unsigned>::max()) | |||
205 | return make_error<CoverageMapError>(coveragemap_error::malformed); | |||
206 | if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max())) | |||
207 | return Err; | |||
208 | if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max())) | |||
209 | return Err; | |||
210 | LineStart += LineStartDelta; | |||
211 | ||||
212 | // If the high bit of ColumnEnd is set, this is a gap region. | |||
213 | if (ColumnEnd & (1U << 31)) { | |||
214 | Kind = CounterMappingRegion::GapRegion; | |||
215 | ColumnEnd &= ~(1U << 31); | |||
216 | } | |||
217 | ||||
218 | // Adjust the column locations for the empty regions that are supposed to | |||
219 | // cover whole lines. Those regions should be encoded with the | |||
220 | // column range (1 -> std::numeric_limits<unsigned>::max()), but because | |||
221 | // the encoded std::numeric_limits<unsigned>::max() is several bytes long, | |||
222 | // we set the column range to (0 -> 0) to ensure that the column start and | |||
223 | // column end take up one byte each. | |||
224 | // The std::numeric_limits<unsigned>::max() is used to represent a column | |||
225 | // position at the end of the line without knowing the length of that line. | |||
226 | if (ColumnStart == 0 && ColumnEnd == 0) { | |||
227 | ColumnStart = 1; | |||
228 | ColumnEnd = std::numeric_limits<unsigned>::max(); | |||
229 | } | |||
230 | ||||
231 | DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coverage-mapping")) { { dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":" << ColumnStart << " -> " << (LineStart + NumLines ) << ":" << ColumnEnd << ", "; if (Kind == CounterMappingRegion ::ExpansionRegion) dbgs() << "Expands to file " << ExpandedFileID; else CounterMappingContext(Expressions).dump (C, dbgs()); dbgs() << "\n"; }; } } while (false) | |||
232 | dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coverage-mapping")) { { dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":" << ColumnStart << " -> " << (LineStart + NumLines ) << ":" << ColumnEnd << ", "; if (Kind == CounterMappingRegion ::ExpansionRegion) dbgs() << "Expands to file " << ExpandedFileID; else CounterMappingContext(Expressions).dump (C, dbgs()); dbgs() << "\n"; }; } } while (false) | |||
233 | << ColumnStart << " -> " << (LineStart + NumLines) << ":"do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coverage-mapping")) { { dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":" << ColumnStart << " -> " << (LineStart + NumLines ) << ":" << ColumnEnd << ", "; if (Kind == CounterMappingRegion ::ExpansionRegion) dbgs() << "Expands to file " << ExpandedFileID; else CounterMappingContext(Expressions).dump (C, dbgs()); dbgs() << "\n"; }; } } while (false) | |||
234 | << ColumnEnd << ", ";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coverage-mapping")) { { dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":" << ColumnStart << " -> " << (LineStart + NumLines ) << ":" << ColumnEnd << ", "; if (Kind == CounterMappingRegion ::ExpansionRegion) dbgs() << "Expands to file " << ExpandedFileID; else CounterMappingContext(Expressions).dump (C, dbgs()); dbgs() << "\n"; }; } } while (false) | |||
235 | if (Kind == CounterMappingRegion::ExpansionRegion)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coverage-mapping")) { { dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":" << ColumnStart << " -> " << (LineStart + NumLines ) << ":" << ColumnEnd << ", "; if (Kind == CounterMappingRegion ::ExpansionRegion) dbgs() << "Expands to file " << ExpandedFileID; else CounterMappingContext(Expressions).dump (C, dbgs()); dbgs() << "\n"; }; } } while (false) | |||
236 | dbgs() << "Expands to file " << ExpandedFileID;do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coverage-mapping")) { { dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":" << ColumnStart << " -> " << (LineStart + NumLines ) << ":" << ColumnEnd << ", "; if (Kind == CounterMappingRegion ::ExpansionRegion) dbgs() << "Expands to file " << ExpandedFileID; else CounterMappingContext(Expressions).dump (C, dbgs()); dbgs() << "\n"; }; } } while (false) | |||
237 | elsedo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coverage-mapping")) { { dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":" << ColumnStart << " -> " << (LineStart + NumLines ) << ":" << ColumnEnd << ", "; if (Kind == CounterMappingRegion ::ExpansionRegion) dbgs() << "Expands to file " << ExpandedFileID; else CounterMappingContext(Expressions).dump (C, dbgs()); dbgs() << "\n"; }; } } while (false) | |||
238 | CounterMappingContext(Expressions).dump(C, dbgs());do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coverage-mapping")) { { dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":" << ColumnStart << " -> " << (LineStart + NumLines ) << ":" << ColumnEnd << ", "; if (Kind == CounterMappingRegion ::ExpansionRegion) dbgs() << "Expands to file " << ExpandedFileID; else CounterMappingContext(Expressions).dump (C, dbgs()); dbgs() << "\n"; }; } } while (false) | |||
239 | dbgs() << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coverage-mapping")) { { dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":" << ColumnStart << " -> " << (LineStart + NumLines ) << ":" << ColumnEnd << ", "; if (Kind == CounterMappingRegion ::ExpansionRegion) dbgs() << "Expands to file " << ExpandedFileID; else CounterMappingContext(Expressions).dump (C, dbgs()); dbgs() << "\n"; }; } } while (false) | |||
240 | })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coverage-mapping")) { { dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":" << ColumnStart << " -> " << (LineStart + NumLines ) << ":" << ColumnEnd << ", "; if (Kind == CounterMappingRegion ::ExpansionRegion) dbgs() << "Expands to file " << ExpandedFileID; else CounterMappingContext(Expressions).dump (C, dbgs()); dbgs() << "\n"; }; } } while (false); | |||
241 | ||||
242 | auto CMR = CounterMappingRegion(C, InferredFileID, ExpandedFileID, | |||
243 | LineStart, ColumnStart, | |||
244 | LineStart + NumLines, ColumnEnd, Kind); | |||
245 | if (CMR.startLoc() > CMR.endLoc()) | |||
246 | return make_error<CoverageMapError>(coveragemap_error::malformed); | |||
247 | MappingRegions.push_back(CMR); | |||
248 | } | |||
249 | return Error::success(); | |||
250 | } | |||
251 | ||||
252 | Error RawCoverageMappingReader::read() { | |||
253 | // Read the virtual file mapping. | |||
254 | SmallVector<unsigned, 8> VirtualFileMapping; | |||
255 | uint64_t NumFileMappings; | |||
256 | if (auto Err = readSize(NumFileMappings)) | |||
257 | return Err; | |||
258 | for (size_t I = 0; I < NumFileMappings; ++I) { | |||
259 | uint64_t FilenameIndex; | |||
260 | if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size())) | |||
261 | return Err; | |||
262 | VirtualFileMapping.push_back(FilenameIndex); | |||
263 | } | |||
264 | ||||
265 | // Construct the files using unique filenames and virtual file mapping. | |||
266 | for (auto I : VirtualFileMapping) { | |||
267 | Filenames.push_back(TranslationUnitFilenames[I]); | |||
268 | } | |||
269 | ||||
270 | // Read the expressions. | |||
271 | uint64_t NumExpressions; | |||
272 | if (auto Err = readSize(NumExpressions)) | |||
273 | return Err; | |||
274 | // Create an array of dummy expressions that get the proper counters | |||
275 | // when the expressions are read, and the proper kinds when the counters | |||
276 | // are decoded. | |||
277 | Expressions.resize( | |||
278 | NumExpressions, | |||
279 | CounterExpression(CounterExpression::Subtract, Counter(), Counter())); | |||
280 | for (size_t I = 0; I < NumExpressions; ++I) { | |||
281 | if (auto Err = readCounter(Expressions[I].LHS)) | |||
282 | return Err; | |||
283 | if (auto Err = readCounter(Expressions[I].RHS)) | |||
284 | return Err; | |||
285 | } | |||
286 | ||||
287 | // Read the mapping regions sub-arrays. | |||
288 | for (unsigned InferredFileID = 0, S = VirtualFileMapping.size(); | |||
289 | InferredFileID < S; ++InferredFileID) { | |||
290 | if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID, | |||
291 | VirtualFileMapping.size())) | |||
292 | return Err; | |||
293 | } | |||
294 | ||||
295 | // Set the counters for the expansion regions. | |||
296 | // i.e. Counter of expansion region = counter of the first region | |||
297 | // from the expanded file. | |||
298 | // Perform multiple passes to correctly propagate the counters through | |||
299 | // all the nested expansion regions. | |||
300 | SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping; | |||
301 | FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr); | |||
302 | for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) { | |||
303 | for (auto &R : MappingRegions) { | |||
304 | if (R.Kind != CounterMappingRegion::ExpansionRegion) | |||
305 | continue; | |||
306 | assert(!FileIDExpansionRegionMapping[R.ExpandedFileID])(static_cast <bool> (!FileIDExpansionRegionMapping[R.ExpandedFileID ]) ? void (0) : __assert_fail ("!FileIDExpansionRegionMapping[R.ExpandedFileID]" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/ProfileData/Coverage/CoverageMappingReader.cpp" , 306, __extension__ __PRETTY_FUNCTION__)); | |||
307 | FileIDExpansionRegionMapping[R.ExpandedFileID] = &R; | |||
308 | } | |||
309 | for (auto &R : MappingRegions) { | |||
310 | if (FileIDExpansionRegionMapping[R.FileID]) { | |||
311 | FileIDExpansionRegionMapping[R.FileID]->Count = R.Count; | |||
312 | FileIDExpansionRegionMapping[R.FileID] = nullptr; | |||
313 | } | |||
314 | } | |||
315 | } | |||
316 | ||||
317 | return Error::success(); | |||
318 | } | |||
319 | ||||
320 | Expected<bool> RawCoverageMappingDummyChecker::isDummy() { | |||
321 | // A dummy coverage mapping data consists of just one region with zero count. | |||
322 | uint64_t NumFileMappings; | |||
323 | if (Error Err = readSize(NumFileMappings)) | |||
324 | return std::move(Err); | |||
325 | if (NumFileMappings != 1) | |||
326 | return false; | |||
327 | // We don't expect any specific value for the filename index, just skip it. | |||
328 | uint64_t FilenameIndex; | |||
329 | if (Error Err = | |||
330 | readIntMax(FilenameIndex, std::numeric_limits<unsigned>::max())) | |||
331 | return std::move(Err); | |||
332 | uint64_t NumExpressions; | |||
333 | if (Error Err = readSize(NumExpressions)) | |||
334 | return std::move(Err); | |||
335 | if (NumExpressions != 0) | |||
336 | return false; | |||
337 | uint64_t NumRegions; | |||
338 | if (Error Err = readSize(NumRegions)) | |||
339 | return std::move(Err); | |||
340 | if (NumRegions != 1) | |||
341 | return false; | |||
342 | uint64_t EncodedCounterAndRegion; | |||
343 | if (Error Err = readIntMax(EncodedCounterAndRegion, | |||
344 | std::numeric_limits<unsigned>::max())) | |||
345 | return std::move(Err); | |||
346 | unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask; | |||
347 | return Tag == Counter::Zero; | |||
348 | } | |||
349 | ||||
350 | Error InstrProfSymtab::create(SectionRef &Section) { | |||
351 | if (auto EC = Section.getContents(Data)) | |||
352 | return errorCodeToError(EC); | |||
353 | Address = Section.getAddress(); | |||
354 | return Error::success(); | |||
355 | } | |||
356 | ||||
357 | StringRef InstrProfSymtab::getFuncName(uint64_t Pointer, size_t Size) { | |||
358 | if (Pointer < Address) | |||
359 | return StringRef(); | |||
360 | auto Offset = Pointer - Address; | |||
361 | if (Offset + Size > Data.size()) | |||
362 | return StringRef(); | |||
363 | return Data.substr(Pointer - Address, Size); | |||
364 | } | |||
365 | ||||
366 | // Check if the mapping data is a dummy, i.e. is emitted for an unused function. | |||
367 | static Expected<bool> isCoverageMappingDummy(uint64_t Hash, StringRef Mapping) { | |||
368 | // The hash value of dummy mapping records is always zero. | |||
369 | if (Hash) | |||
370 | return false; | |||
371 | return RawCoverageMappingDummyChecker(Mapping).isDummy(); | |||
372 | } | |||
373 | ||||
374 | namespace { | |||
375 | ||||
376 | struct CovMapFuncRecordReader { | |||
377 | virtual ~CovMapFuncRecordReader() = default; | |||
378 | ||||
379 | // The interface to read coverage mapping function records for a module. | |||
380 | // | |||
381 | // \p Buf points to the buffer containing the \c CovHeader of the coverage | |||
382 | // mapping data associated with the module. | |||
383 | // | |||
384 | // Returns a pointer to the next \c CovHeader if it exists, or a pointer | |||
385 | // greater than \p End if not. | |||
386 | virtual Expected<const char *> readFunctionRecords(const char *Buf, | |||
387 | const char *End) = 0; | |||
388 | ||||
389 | template <class IntPtrT, support::endianness Endian> | |||
390 | static Expected<std::unique_ptr<CovMapFuncRecordReader>> | |||
391 | get(CovMapVersion Version, InstrProfSymtab &P, | |||
392 | std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, | |||
393 | std::vector<StringRef> &F); | |||
394 | }; | |||
395 | ||||
396 | // A class for reading coverage mapping function records for a module. | |||
397 | template <CovMapVersion Version, class IntPtrT, support::endianness Endian> | |||
398 | class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader { | |||
399 | using FuncRecordType = | |||
400 | typename CovMapTraits<Version, IntPtrT>::CovMapFuncRecordType; | |||
401 | using NameRefType = typename CovMapTraits<Version, IntPtrT>::NameRefType; | |||
402 | ||||
403 | // Maps function's name references to the indexes of their records | |||
404 | // in \c Records. | |||
405 | DenseMap<NameRefType, size_t> FunctionRecords; | |||
406 | InstrProfSymtab &ProfileNames; | |||
407 | std::vector<StringRef> &Filenames; | |||
408 | std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records; | |||
409 | ||||
410 | // Add the record to the collection if we don't already have a record that | |||
411 | // points to the same function name. This is useful to ignore the redundant | |||
412 | // records for the functions with ODR linkage. | |||
413 | // In addition, prefer records with real coverage mapping data to dummy | |||
414 | // records, which were emitted for inline functions which were seen but | |||
415 | // not used in the corresponding translation unit. | |||
416 | Error insertFunctionRecordIfNeeded(const FuncRecordType *CFR, | |||
417 | StringRef Mapping, size_t FilenamesBegin) { | |||
418 | uint64_t FuncHash = CFR->template getFuncHash<Endian>(); | |||
419 | NameRefType NameRef = CFR->template getFuncNameRef<Endian>(); | |||
420 | auto InsertResult = | |||
421 | FunctionRecords.insert(std::make_pair(NameRef, Records.size())); | |||
422 | if (InsertResult.second) { | |||
423 | StringRef FuncName; | |||
424 | if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName)) | |||
425 | return Err; | |||
426 | if (FuncName.empty()) | |||
427 | return make_error<InstrProfError>(instrprof_error::malformed); | |||
428 | Records.emplace_back(Version, FuncName, FuncHash, Mapping, FilenamesBegin, | |||
429 | Filenames.size() - FilenamesBegin); | |||
430 | return Error::success(); | |||
431 | } | |||
432 | // Update the existing record if it's a dummy and the new record is real. | |||
433 | size_t OldRecordIndex = InsertResult.first->second; | |||
434 | BinaryCoverageReader::ProfileMappingRecord &OldRecord = | |||
435 | Records[OldRecordIndex]; | |||
436 | Expected<bool> OldIsDummyExpected = isCoverageMappingDummy( | |||
437 | OldRecord.FunctionHash, OldRecord.CoverageMapping); | |||
438 | if (Error Err = OldIsDummyExpected.takeError()) | |||
439 | return Err; | |||
440 | if (!*OldIsDummyExpected) | |||
441 | return Error::success(); | |||
442 | Expected<bool> NewIsDummyExpected = | |||
443 | isCoverageMappingDummy(FuncHash, Mapping); | |||
444 | if (Error Err = NewIsDummyExpected.takeError()) | |||
445 | return Err; | |||
446 | if (*NewIsDummyExpected) | |||
447 | return Error::success(); | |||
448 | OldRecord.FunctionHash = FuncHash; | |||
449 | OldRecord.CoverageMapping = Mapping; | |||
450 | OldRecord.FilenamesBegin = FilenamesBegin; | |||
451 | OldRecord.FilenamesSize = Filenames.size() - FilenamesBegin; | |||
452 | return Error::success(); | |||
453 | } | |||
454 | ||||
455 | public: | |||
456 | VersionedCovMapFuncRecordReader( | |||
457 | InstrProfSymtab &P, | |||
458 | std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, | |||
459 | std::vector<StringRef> &F) | |||
460 | : ProfileNames(P), Filenames(F), Records(R) {} | |||
461 | ||||
462 | ~VersionedCovMapFuncRecordReader() override = default; | |||
463 | ||||
464 | Expected<const char *> readFunctionRecords(const char *Buf, | |||
465 | const char *End) override { | |||
466 | using namespace support; | |||
467 | ||||
468 | if (Buf + sizeof(CovMapHeader) > End) | |||
469 | return make_error<CoverageMapError>(coveragemap_error::malformed); | |||
470 | auto CovHeader = reinterpret_cast<const CovMapHeader *>(Buf); | |||
471 | uint32_t NRecords = CovHeader->getNRecords<Endian>(); | |||
472 | uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>(); | |||
473 | uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>(); | |||
474 | assert((CovMapVersion)CovHeader->getVersion<Endian>() == Version)(static_cast <bool> ((CovMapVersion)CovHeader->getVersion <Endian>() == Version) ? void (0) : __assert_fail ("(CovMapVersion)CovHeader->getVersion<Endian>() == Version" , "/build/llvm-toolchain-snapshot-7~svn326246/lib/ProfileData/Coverage/CoverageMappingReader.cpp" , 474, __extension__ __PRETTY_FUNCTION__)); | |||
475 | Buf = reinterpret_cast<const char *>(CovHeader + 1); | |||
476 | ||||
477 | // Skip past the function records, saving the start and end for later. | |||
478 | const char *FunBuf = Buf; | |||
479 | Buf += NRecords * sizeof(FuncRecordType); | |||
480 | const char *FunEnd = Buf; | |||
481 | ||||
482 | // Get the filenames. | |||
483 | if (Buf + FilenamesSize > End) | |||
484 | return make_error<CoverageMapError>(coveragemap_error::malformed); | |||
485 | size_t FilenamesBegin = Filenames.size(); | |||
486 | RawCoverageFilenamesReader Reader(StringRef(Buf, FilenamesSize), Filenames); | |||
487 | if (auto Err = Reader.read()) | |||
488 | return std::move(Err); | |||
489 | Buf += FilenamesSize; | |||
490 | ||||
491 | // We'll read the coverage mapping records in the loop below. | |||
492 | const char *CovBuf = Buf; | |||
493 | Buf += CoverageSize; | |||
494 | const char *CovEnd = Buf; | |||
495 | ||||
496 | if (Buf > End) | |||
497 | return make_error<CoverageMapError>(coveragemap_error::malformed); | |||
498 | // Each coverage map has an alignment of 8, so we need to adjust alignment | |||
499 | // before reading the next map. | |||
500 | Buf += alignmentAdjustment(Buf, 8); | |||
501 | ||||
502 | auto CFR = reinterpret_cast<const FuncRecordType *>(FunBuf); | |||
503 | while ((const char *)CFR < FunEnd) { | |||
504 | // Read the function information | |||
505 | uint32_t DataSize = CFR->template getDataSize<Endian>(); | |||
506 | ||||
507 | // Now use that to read the coverage data. | |||
508 | if (CovBuf + DataSize > CovEnd) | |||
509 | return make_error<CoverageMapError>(coveragemap_error::malformed); | |||
510 | auto Mapping = StringRef(CovBuf, DataSize); | |||
511 | CovBuf += DataSize; | |||
512 | ||||
513 | if (Error Err = | |||
514 | insertFunctionRecordIfNeeded(CFR, Mapping, FilenamesBegin)) | |||
515 | return std::move(Err); | |||
516 | CFR++; | |||
517 | } | |||
518 | return Buf; | |||
519 | } | |||
520 | }; | |||
521 | ||||
522 | } // end anonymous namespace | |||
523 | ||||
524 | template <class IntPtrT, support::endianness Endian> | |||
525 | Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get( | |||
526 | CovMapVersion Version, InstrProfSymtab &P, | |||
527 | std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, | |||
528 | std::vector<StringRef> &F) { | |||
529 | using namespace coverage; | |||
530 | ||||
531 | switch (Version) { | |||
532 | case CovMapVersion::Version1: | |||
533 | return llvm::make_unique<VersionedCovMapFuncRecordReader< | |||
534 | CovMapVersion::Version1, IntPtrT, Endian>>(P, R, F); | |||
535 | case CovMapVersion::Version2: | |||
536 | case CovMapVersion::Version3: | |||
537 | // Decompress the name data. | |||
538 | if (Error E = P.create(P.getNameData())) | |||
539 | return std::move(E); | |||
540 | if (Version == CovMapVersion::Version2) | |||
541 | return llvm::make_unique<VersionedCovMapFuncRecordReader< | |||
542 | CovMapVersion::Version2, IntPtrT, Endian>>(P, R, F); | |||
543 | else | |||
544 | return llvm::make_unique<VersionedCovMapFuncRecordReader< | |||
545 | CovMapVersion::Version3, IntPtrT, Endian>>(P, R, F); | |||
546 | } | |||
547 | llvm_unreachable("Unsupported version")::llvm::llvm_unreachable_internal("Unsupported version", "/build/llvm-toolchain-snapshot-7~svn326246/lib/ProfileData/Coverage/CoverageMappingReader.cpp" , 547); | |||
548 | } | |||
549 | ||||
550 | template <typename T, support::endianness Endian> | |||
551 | static Error readCoverageMappingData( | |||
552 | InstrProfSymtab &ProfileNames, StringRef Data, | |||
553 | std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records, | |||
554 | std::vector<StringRef> &Filenames) { | |||
555 | using namespace coverage; | |||
556 | ||||
557 | // Read the records in the coverage data section. | |||
558 | auto CovHeader = | |||
559 | reinterpret_cast<const CovMapHeader *>(Data.data()); | |||
560 | CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>(); | |||
561 | if (Version > CovMapVersion::CurrentVersion) | |||
562 | return make_error<CoverageMapError>(coveragemap_error::unsupported_version); | |||
563 | Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected = | |||
564 | CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records, | |||
565 | Filenames); | |||
566 | if (Error E = ReaderExpected.takeError()) | |||
567 | return E; | |||
568 | auto Reader = std::move(ReaderExpected.get()); | |||
569 | for (const char *Buf = Data.data(), *End = Buf + Data.size(); Buf < End;) { | |||
570 | auto NextHeaderOrErr = Reader->readFunctionRecords(Buf, End); | |||
571 | if (auto E = NextHeaderOrErr.takeError()) | |||
572 | return E; | |||
573 | Buf = NextHeaderOrErr.get(); | |||
574 | } | |||
575 | return Error::success(); | |||
576 | } | |||
577 | ||||
578 | static const char *TestingFormatMagic = "llvmcovmtestdata"; | |||
579 | ||||
580 | static Error loadTestingFormat(StringRef Data, InstrProfSymtab &ProfileNames, | |||
581 | StringRef &CoverageMapping, | |||
582 | uint8_t &BytesInAddress, | |||
583 | support::endianness &Endian) { | |||
584 | BytesInAddress = 8; | |||
585 | Endian = support::endianness::little; | |||
586 | ||||
587 | Data = Data.substr(StringRef(TestingFormatMagic).size()); | |||
588 | if (Data.empty()) | |||
589 | return make_error<CoverageMapError>(coveragemap_error::truncated); | |||
590 | unsigned N = 0; | |||
591 | auto ProfileNamesSize = | |||
592 | decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N); | |||
593 | if (N > Data.size()) | |||
594 | return make_error<CoverageMapError>(coveragemap_error::malformed); | |||
595 | Data = Data.substr(N); | |||
596 | if (Data.empty()) | |||
597 | return make_error<CoverageMapError>(coveragemap_error::truncated); | |||
598 | N = 0; | |||
599 | uint64_t Address = | |||
600 | decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N); | |||
601 | if (N > Data.size()) | |||
602 | return make_error<CoverageMapError>(coveragemap_error::malformed); | |||
603 | Data = Data.substr(N); | |||
604 | if (Data.size() < ProfileNamesSize) | |||
605 | return make_error<CoverageMapError>(coveragemap_error::malformed); | |||
606 | if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address)) | |||
607 | return E; | |||
608 | CoverageMapping = Data.substr(ProfileNamesSize); | |||
609 | // Skip the padding bytes because coverage map data has an alignment of 8. | |||
610 | if (CoverageMapping.empty()) | |||
611 | return make_error<CoverageMapError>(coveragemap_error::truncated); | |||
612 | size_t Pad = alignmentAdjustment(CoverageMapping.data(), 8); | |||
613 | if (CoverageMapping.size() < Pad) | |||
614 | return make_error<CoverageMapError>(coveragemap_error::malformed); | |||
615 | CoverageMapping = CoverageMapping.substr(Pad); | |||
616 | return Error::success(); | |||
617 | } | |||
618 | ||||
619 | static Expected<SectionRef> lookupSection(ObjectFile &OF, StringRef Name) { | |||
620 | StringRef FoundName; | |||
621 | for (const auto &Section : OF.sections()) { | |||
622 | if (auto EC = Section.getName(FoundName)) | |||
623 | return errorCodeToError(EC); | |||
624 | if (FoundName == Name) | |||
625 | return Section; | |||
626 | } | |||
627 | return make_error<CoverageMapError>(coveragemap_error::no_data_found); | |||
628 | } | |||
629 | ||||
630 | static Error loadBinaryFormat(MemoryBufferRef ObjectBuffer, | |||
631 | InstrProfSymtab &ProfileNames, | |||
632 | StringRef &CoverageMapping, | |||
633 | uint8_t &BytesInAddress, | |||
634 | support::endianness &Endian, StringRef Arch) { | |||
635 | auto BinOrErr = createBinary(ObjectBuffer); | |||
636 | if (!BinOrErr) | |||
637 | return BinOrErr.takeError(); | |||
638 | auto Bin = std::move(BinOrErr.get()); | |||
639 | std::unique_ptr<ObjectFile> OF; | |||
640 | if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) { | |||
641 | // If we have a universal binary, try to look up the object for the | |||
642 | // appropriate architecture. | |||
643 | auto ObjectFileOrErr = Universal->getObjectForArch(Arch); | |||
644 | if (!ObjectFileOrErr) | |||
645 | return ObjectFileOrErr.takeError(); | |||
646 | OF = std::move(ObjectFileOrErr.get()); | |||
647 | } else if (isa<ObjectFile>(Bin.get())) { | |||
648 | // For any other object file, upcast and take ownership. | |||
649 | OF.reset(cast<ObjectFile>(Bin.release())); | |||
650 | // If we've asked for a particular arch, make sure they match. | |||
651 | if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch()) | |||
652 | return errorCodeToError(object_error::arch_not_found); | |||
653 | } else | |||
654 | // We can only handle object files. | |||
655 | return make_error<CoverageMapError>(coveragemap_error::malformed); | |||
656 | ||||
657 | // The coverage uses native pointer sizes for the object it's written in. | |||
658 | BytesInAddress = OF->getBytesInAddress(); | |||
659 | Endian = OF->isLittleEndian() ? support::endianness::little | |||
660 | : support::endianness::big; | |||
661 | ||||
662 | // Look for the sections that we are interested in. | |||
663 | auto ObjFormat = OF->getTripleObjectFormat(); | |||
664 | auto NamesSection = | |||
665 | lookupSection(*OF, getInstrProfSectionName(IPSK_name, ObjFormat, | |||
666 | /*AddSegmentInfo=*/false)); | |||
667 | if (auto E = NamesSection.takeError()) | |||
668 | return E; | |||
669 | auto CoverageSection = | |||
670 | lookupSection(*OF, getInstrProfSectionName(IPSK_covmap, ObjFormat, | |||
671 | /*AddSegmentInfo=*/false)); | |||
672 | if (auto E = CoverageSection.takeError()) | |||
673 | return E; | |||
674 | ||||
675 | // Get the contents of the given sections. | |||
676 | if (auto EC = CoverageSection->getContents(CoverageMapping)) | |||
677 | return errorCodeToError(EC); | |||
678 | if (Error E = ProfileNames.create(*NamesSection)) | |||
679 | return E; | |||
680 | ||||
681 | return Error::success(); | |||
682 | } | |||
683 | ||||
684 | Expected<std::unique_ptr<BinaryCoverageReader>> | |||
685 | BinaryCoverageReader::create(std::unique_ptr<MemoryBuffer> &ObjectBuffer, | |||
686 | StringRef Arch) { | |||
687 | std::unique_ptr<BinaryCoverageReader> Reader(new BinaryCoverageReader()); | |||
688 | ||||
689 | StringRef Coverage; | |||
690 | uint8_t BytesInAddress; | |||
691 | support::endianness Endian; | |||
692 | Error E = Error::success(); | |||
693 | consumeError(std::move(E)); | |||
694 | if (ObjectBuffer->getBuffer().startswith(TestingFormatMagic)) | |||
695 | // This is a special format used for testing. | |||
696 | E = loadTestingFormat(ObjectBuffer->getBuffer(), Reader->ProfileNames, | |||
697 | Coverage, BytesInAddress, Endian); | |||
698 | else | |||
699 | E = loadBinaryFormat(ObjectBuffer->getMemBufferRef(), Reader->ProfileNames, | |||
700 | Coverage, BytesInAddress, Endian, Arch); | |||
701 | if (E) | |||
702 | return std::move(E); | |||
703 | ||||
704 | if (BytesInAddress == 4 && Endian == support::endianness::little) | |||
705 | E = readCoverageMappingData<uint32_t, support::endianness::little>( | |||
706 | Reader->ProfileNames, Coverage, Reader->MappingRecords, | |||
707 | Reader->Filenames); | |||
708 | else if (BytesInAddress == 4 && Endian == support::endianness::big) | |||
709 | E = readCoverageMappingData<uint32_t, support::endianness::big>( | |||
710 | Reader->ProfileNames, Coverage, Reader->MappingRecords, | |||
711 | Reader->Filenames); | |||
712 | else if (BytesInAddress == 8 && Endian == support::endianness::little) | |||
713 | E = readCoverageMappingData<uint64_t, support::endianness::little>( | |||
714 | Reader->ProfileNames, Coverage, Reader->MappingRecords, | |||
715 | Reader->Filenames); | |||
716 | else if (BytesInAddress == 8 && Endian == support::endianness::big) | |||
717 | E = readCoverageMappingData<uint64_t, support::endianness::big>( | |||
718 | Reader->ProfileNames, Coverage, Reader->MappingRecords, | |||
719 | Reader->Filenames); | |||
720 | else | |||
721 | return make_error<CoverageMapError>(coveragemap_error::malformed); | |||
722 | if (E) | |||
723 | return std::move(E); | |||
724 | return std::move(Reader); | |||
725 | } | |||
726 | ||||
727 | Error BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) { | |||
728 | if (CurrentRecord >= MappingRecords.size()) | |||
729 | return make_error<CoverageMapError>(coveragemap_error::eof); | |||
730 | ||||
731 | FunctionsFilenames.clear(); | |||
732 | Expressions.clear(); | |||
733 | MappingRegions.clear(); | |||
734 | auto &R = MappingRecords[CurrentRecord]; | |||
735 | RawCoverageMappingReader Reader( | |||
736 | R.CoverageMapping, | |||
737 | makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize), | |||
738 | FunctionsFilenames, Expressions, MappingRegions); | |||
739 | if (auto Err = Reader.read()) | |||
740 | return Err; | |||
741 | ||||
742 | Record.FunctionName = R.FunctionName; | |||
743 | Record.FunctionHash = R.FunctionHash; | |||
744 | Record.Filenames = FunctionsFilenames; | |||
745 | Record.Expressions = Expressions; | |||
746 | Record.MappingRegions = MappingRegions; | |||
747 | ||||
748 | ++CurrentRecord; | |||
749 | return Error::success(); | |||
750 | } |
1 | //===- llvm/Support/Error.h - Recoverable error handling --------*- C++ -*-===// |
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 defines an API used to report recoverable errors. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_SUPPORT_ERROR_H |
15 | #define LLVM_SUPPORT_ERROR_H |
16 | |
17 | #include "llvm/ADT/SmallVector.h" |
18 | #include "llvm/ADT/STLExtras.h" |
19 | #include "llvm/ADT/StringExtras.h" |
20 | #include "llvm/ADT/Twine.h" |
21 | #include "llvm/Config/abi-breaking.h" |
22 | #include "llvm/Support/AlignOf.h" |
23 | #include "llvm/Support/Compiler.h" |
24 | #include "llvm/Support/Debug.h" |
25 | #include "llvm/Support/ErrorHandling.h" |
26 | #include "llvm/Support/ErrorOr.h" |
27 | #include "llvm/Support/raw_ostream.h" |
28 | #include <algorithm> |
29 | #include <cassert> |
30 | #include <cstdint> |
31 | #include <cstdlib> |
32 | #include <functional> |
33 | #include <memory> |
34 | #include <new> |
35 | #include <string> |
36 | #include <system_error> |
37 | #include <type_traits> |
38 | #include <utility> |
39 | #include <vector> |
40 | |
41 | namespace llvm { |
42 | |
43 | class ErrorSuccess; |
44 | |
45 | /// Base class for error info classes. Do not extend this directly: Extend |
46 | /// the ErrorInfo template subclass instead. |
47 | class ErrorInfoBase { |
48 | public: |
49 | virtual ~ErrorInfoBase() = default; |
50 | |
51 | /// Print an error message to an output stream. |
52 | virtual void log(raw_ostream &OS) const = 0; |
53 | |
54 | /// Return the error message as a string. |
55 | virtual std::string message() const { |
56 | std::string Msg; |
57 | raw_string_ostream OS(Msg); |
58 | log(OS); |
59 | return OS.str(); |
60 | } |
61 | |
62 | /// Convert this error to a std::error_code. |
63 | /// |
64 | /// This is a temporary crutch to enable interaction with code still |
65 | /// using std::error_code. It will be removed in the future. |
66 | virtual std::error_code convertToErrorCode() const = 0; |
67 | |
68 | // Returns the class ID for this type. |
69 | static const void *classID() { return &ID; } |
70 | |
71 | // Returns the class ID for the dynamic type of this ErrorInfoBase instance. |
72 | virtual const void *dynamicClassID() const = 0; |
73 | |
74 | // Check whether this instance is a subclass of the class identified by |
75 | // ClassID. |
76 | virtual bool isA(const void *const ClassID) const { |
77 | return ClassID == classID(); |
78 | } |
79 | |
80 | // Check whether this instance is a subclass of ErrorInfoT. |
81 | template <typename ErrorInfoT> bool isA() const { |
82 | return isA(ErrorInfoT::classID()); |
83 | } |
84 | |
85 | private: |
86 | virtual void anchor(); |
87 | |
88 | static char ID; |
89 | }; |
90 | |
91 | /// Lightweight error class with error context and mandatory checking. |
92 | /// |
93 | /// Instances of this class wrap a ErrorInfoBase pointer. Failure states |
94 | /// are represented by setting the pointer to a ErrorInfoBase subclass |
95 | /// instance containing information describing the failure. Success is |
96 | /// represented by a null pointer value. |
97 | /// |
98 | /// Instances of Error also contains a 'Checked' flag, which must be set |
99 | /// before the destructor is called, otherwise the destructor will trigger a |
100 | /// runtime error. This enforces at runtime the requirement that all Error |
101 | /// instances be checked or returned to the caller. |
102 | /// |
103 | /// There are two ways to set the checked flag, depending on what state the |
104 | /// Error instance is in. For Error instances indicating success, it |
105 | /// is sufficient to invoke the boolean conversion operator. E.g.: |
106 | /// |
107 | /// @code{.cpp} |
108 | /// Error foo(<...>); |
109 | /// |
110 | /// if (auto E = foo(<...>)) |
111 | /// return E; // <- Return E if it is in the error state. |
112 | /// // We have verified that E was in the success state. It can now be safely |
113 | /// // destroyed. |
114 | /// @endcode |
115 | /// |
116 | /// A success value *can not* be dropped. For example, just calling 'foo(<...>)' |
117 | /// without testing the return value will raise a runtime error, even if foo |
118 | /// returns success. |
119 | /// |
120 | /// For Error instances representing failure, you must use either the |
121 | /// handleErrors or handleAllErrors function with a typed handler. E.g.: |
122 | /// |
123 | /// @code{.cpp} |
124 | /// class MyErrorInfo : public ErrorInfo<MyErrorInfo> { |
125 | /// // Custom error info. |
126 | /// }; |
127 | /// |
128 | /// Error foo(<...>) { return make_error<MyErrorInfo>(...); } |
129 | /// |
130 | /// auto E = foo(<...>); // <- foo returns failure with MyErrorInfo. |
131 | /// auto NewE = |
132 | /// handleErrors(E, |
133 | /// [](const MyErrorInfo &M) { |
134 | /// // Deal with the error. |
135 | /// }, |
136 | /// [](std::unique_ptr<OtherError> M) -> Error { |
137 | /// if (canHandle(*M)) { |
138 | /// // handle error. |
139 | /// return Error::success(); |
140 | /// } |
141 | /// // Couldn't handle this error instance. Pass it up the stack. |
142 | /// return Error(std::move(M)); |
143 | /// ); |
144 | /// // Note - we must check or return NewE in case any of the handlers |
145 | /// // returned a new error. |
146 | /// @endcode |
147 | /// |
148 | /// The handleAllErrors function is identical to handleErrors, except |
149 | /// that it has a void return type, and requires all errors to be handled and |
150 | /// no new errors be returned. It prevents errors (assuming they can all be |
151 | /// handled) from having to be bubbled all the way to the top-level. |
152 | /// |
153 | /// *All* Error instances must be checked before destruction, even if |
154 | /// they're moved-assigned or constructed from Success values that have already |
155 | /// been checked. This enforces checking through all levels of the call stack. |
156 | class LLVM_NODISCARD[[clang::warn_unused_result]] Error { |
157 | // ErrorList needs to be able to yank ErrorInfoBase pointers out of this |
158 | // class to add to the error list. |
159 | friend class ErrorList; |
160 | |
161 | // handleErrors needs to be able to set the Checked flag. |
162 | template <typename... HandlerTs> |
163 | friend Error handleErrors(Error E, HandlerTs &&... Handlers); |
164 | |
165 | // Expected<T> needs to be able to steal the payload when constructed from an |
166 | // error. |
167 | template <typename T> friend class Expected; |
168 | |
169 | protected: |
170 | /// Create a success value. Prefer using 'Error::success()' for readability |
171 | Error() { |
172 | setPtr(nullptr); |
173 | setChecked(false); |
174 | } |
175 | |
176 | public: |
177 | /// Create a success value. |
178 | static ErrorSuccess success(); |
179 | |
180 | // Errors are not copy-constructable. |
181 | Error(const Error &Other) = delete; |
182 | |
183 | /// Move-construct an error value. The newly constructed error is considered |
184 | /// unchecked, even if the source error had been checked. The original error |
185 | /// becomes a checked Success value, regardless of its original state. |
186 | Error(Error &&Other) { |
187 | setChecked(true); |
188 | *this = std::move(Other); |
189 | } |
190 | |
191 | /// Create an error value. Prefer using the 'make_error' function, but |
192 | /// this constructor can be useful when "re-throwing" errors from handlers. |
193 | Error(std::unique_ptr<ErrorInfoBase> Payload) { |
194 | setPtr(Payload.release()); |
195 | setChecked(false); |
196 | } |
197 | |
198 | // Errors are not copy-assignable. |
199 | Error &operator=(const Error &Other) = delete; |
200 | |
201 | /// Move-assign an error value. The current error must represent success, you |
202 | /// you cannot overwrite an unhandled error. The current error is then |
203 | /// considered unchecked. The source error becomes a checked success value, |
204 | /// regardless of its original state. |
205 | Error &operator=(Error &&Other) { |
206 | // Don't allow overwriting of unchecked values. |
207 | assertIsChecked(); |
208 | setPtr(Other.getPtr()); |
209 | |
210 | // This Error is unchecked, even if the source error was checked. |
211 | setChecked(false); |
212 | |
213 | // Null out Other's payload and set its checked bit. |
214 | Other.setPtr(nullptr); |
215 | Other.setChecked(true); |
216 | |
217 | return *this; |
218 | } |
219 | |
220 | /// Destroy a Error. Fails with a call to abort() if the error is |
221 | /// unchecked. |
222 | ~Error() { |
223 | assertIsChecked(); |
224 | delete getPtr(); |
225 | } |
226 | |
227 | /// Bool conversion. Returns true if this Error is in a failure state, |
228 | /// and false if it is in an accept state. If the error is in a Success state |
229 | /// it will be considered checked. |
230 | explicit operator bool() { |
231 | setChecked(getPtr() == nullptr); |
232 | return getPtr() != nullptr; |
233 | } |
234 | |
235 | /// Check whether one error is a subclass of another. |
236 | template <typename ErrT> bool isA() const { |
237 | return getPtr() && getPtr()->isA(ErrT::classID()); |
238 | } |
239 | |
240 | /// Returns the dynamic class id of this error, or null if this is a success |
241 | /// value. |
242 | const void* dynamicClassID() const { |
243 | if (!getPtr()) |
244 | return nullptr; |
245 | return getPtr()->dynamicClassID(); |
246 | } |
247 | |
248 | private: |
249 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
250 | // assertIsChecked() happens very frequently, but under normal circumstances |
251 | // is supposed to be a no-op. So we want it to be inlined, but having a bunch |
252 | // of debug prints can cause the function to be too large for inlining. So |
253 | // it's important that we define this function out of line so that it can't be |
254 | // inlined. |
255 | LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) |
256 | void fatalUncheckedError() const; |
257 | #endif |
258 | |
259 | void assertIsChecked() { |
260 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
261 | if (LLVM_UNLIKELY(!getChecked() || getPtr())__builtin_expect((bool)(!getChecked() || getPtr()), false)) |
262 | fatalUncheckedError(); |
263 | #endif |
264 | } |
265 | |
266 | ErrorInfoBase *getPtr() const { |
267 | return reinterpret_cast<ErrorInfoBase*>( |
268 | reinterpret_cast<uintptr_t>(Payload) & |
269 | ~static_cast<uintptr_t>(0x1)); |
270 | } |
271 | |
272 | void setPtr(ErrorInfoBase *EI) { |
273 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
274 | Payload = reinterpret_cast<ErrorInfoBase*>( |
275 | (reinterpret_cast<uintptr_t>(EI) & |
276 | ~static_cast<uintptr_t>(0x1)) | |
277 | (reinterpret_cast<uintptr_t>(Payload) & 0x1)); |
278 | #else |
279 | Payload = EI; |
280 | #endif |
281 | } |
282 | |
283 | bool getChecked() const { |
284 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
285 | return (reinterpret_cast<uintptr_t>(Payload) & 0x1) == 0; |
286 | #else |
287 | return true; |
288 | #endif |
289 | } |
290 | |
291 | void setChecked(bool V) { |
292 | Payload = reinterpret_cast<ErrorInfoBase*>( |
293 | (reinterpret_cast<uintptr_t>(Payload) & |
294 | ~static_cast<uintptr_t>(0x1)) | |
295 | (V ? 0 : 1)); |
296 | } |
297 | |
298 | std::unique_ptr<ErrorInfoBase> takePayload() { |
299 | std::unique_ptr<ErrorInfoBase> Tmp(getPtr()); |
300 | setPtr(nullptr); |
301 | setChecked(true); |
302 | return Tmp; |
303 | } |
304 | |
305 | ErrorInfoBase *Payload = nullptr; |
306 | }; |
307 | |
308 | /// Subclass of Error for the sole purpose of identifying the success path in |
309 | /// the type system. This allows to catch invalid conversion to Expected<T> at |
310 | /// compile time. |
311 | class ErrorSuccess : public Error {}; |
312 | |
313 | inline ErrorSuccess Error::success() { return ErrorSuccess(); } |
314 | |
315 | /// Make a Error instance representing failure using the given error info |
316 | /// type. |
317 | template <typename ErrT, typename... ArgTs> Error make_error(ArgTs &&... Args) { |
318 | return Error(llvm::make_unique<ErrT>(std::forward<ArgTs>(Args)...)); |
319 | } |
320 | |
321 | /// Base class for user error types. Users should declare their error types |
322 | /// like: |
323 | /// |
324 | /// class MyError : public ErrorInfo<MyError> { |
325 | /// .... |
326 | /// }; |
327 | /// |
328 | /// This class provides an implementation of the ErrorInfoBase::kind |
329 | /// method, which is used by the Error RTTI system. |
330 | template <typename ThisErrT, typename ParentErrT = ErrorInfoBase> |
331 | class ErrorInfo : public ParentErrT { |
332 | public: |
333 | static const void *classID() { return &ThisErrT::ID; } |
334 | |
335 | const void *dynamicClassID() const override { return &ThisErrT::ID; } |
336 | |
337 | bool isA(const void *const ClassID) const override { |
338 | return ClassID == classID() || ParentErrT::isA(ClassID); |
339 | } |
340 | }; |
341 | |
342 | /// Special ErrorInfo subclass representing a list of ErrorInfos. |
343 | /// Instances of this class are constructed by joinError. |
344 | class ErrorList final : public ErrorInfo<ErrorList> { |
345 | // handleErrors needs to be able to iterate the payload list of an |
346 | // ErrorList. |
347 | template <typename... HandlerTs> |
348 | friend Error handleErrors(Error E, HandlerTs &&... Handlers); |
349 | |
350 | // joinErrors is implemented in terms of join. |
351 | friend Error joinErrors(Error, Error); |
352 | |
353 | public: |
354 | void log(raw_ostream &OS) const override { |
355 | OS << "Multiple errors:\n"; |
356 | for (auto &ErrPayload : Payloads) { |
357 | ErrPayload->log(OS); |
358 | OS << "\n"; |
359 | } |
360 | } |
361 | |
362 | std::error_code convertToErrorCode() const override; |
363 | |
364 | // Used by ErrorInfo::classID. |
365 | static char ID; |
366 | |
367 | private: |
368 | ErrorList(std::unique_ptr<ErrorInfoBase> Payload1, |
369 | std::unique_ptr<ErrorInfoBase> Payload2) { |
370 | assert(!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() &&(static_cast <bool> (!Payload1->isA<ErrorList> () && !Payload2->isA<ErrorList>() && "ErrorList constructor payloads should be singleton errors") ? void (0) : __assert_fail ("!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() && \"ErrorList constructor payloads should be singleton errors\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/Support/Error.h" , 371, __extension__ __PRETTY_FUNCTION__)) |
371 | "ErrorList constructor payloads should be singleton errors")(static_cast <bool> (!Payload1->isA<ErrorList> () && !Payload2->isA<ErrorList>() && "ErrorList constructor payloads should be singleton errors") ? void (0) : __assert_fail ("!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() && \"ErrorList constructor payloads should be singleton errors\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/Support/Error.h" , 371, __extension__ __PRETTY_FUNCTION__)); |
372 | Payloads.push_back(std::move(Payload1)); |
373 | Payloads.push_back(std::move(Payload2)); |
374 | } |
375 | |
376 | static Error join(Error E1, Error E2) { |
377 | if (!E1) |
378 | return E2; |
379 | if (!E2) |
380 | return E1; |
381 | if (E1.isA<ErrorList>()) { |
382 | auto &E1List = static_cast<ErrorList &>(*E1.getPtr()); |
383 | if (E2.isA<ErrorList>()) { |
384 | auto E2Payload = E2.takePayload(); |
385 | auto &E2List = static_cast<ErrorList &>(*E2Payload); |
386 | for (auto &Payload : E2List.Payloads) |
387 | E1List.Payloads.push_back(std::move(Payload)); |
388 | } else |
389 | E1List.Payloads.push_back(E2.takePayload()); |
390 | |
391 | return E1; |
392 | } |
393 | if (E2.isA<ErrorList>()) { |
394 | auto &E2List = static_cast<ErrorList &>(*E2.getPtr()); |
395 | E2List.Payloads.insert(E2List.Payloads.begin(), E1.takePayload()); |
396 | return E2; |
397 | } |
398 | return Error(std::unique_ptr<ErrorList>( |
399 | new ErrorList(E1.takePayload(), E2.takePayload()))); |
400 | } |
401 | |
402 | std::vector<std::unique_ptr<ErrorInfoBase>> Payloads; |
403 | }; |
404 | |
405 | /// Concatenate errors. The resulting Error is unchecked, and contains the |
406 | /// ErrorInfo(s), if any, contained in E1, followed by the |
407 | /// ErrorInfo(s), if any, contained in E2. |
408 | inline Error joinErrors(Error E1, Error E2) { |
409 | return ErrorList::join(std::move(E1), std::move(E2)); |
410 | } |
411 | |
412 | /// Tagged union holding either a T or a Error. |
413 | /// |
414 | /// This class parallels ErrorOr, but replaces error_code with Error. Since |
415 | /// Error cannot be copied, this class replaces getError() with |
416 | /// takeError(). It also adds an bool errorIsA<ErrT>() method for testing the |
417 | /// error class type. |
418 | template <class T> class LLVM_NODISCARD[[clang::warn_unused_result]] Expected { |
419 | template <class T1> friend class ExpectedAsOutParameter; |
420 | template <class OtherT> friend class Expected; |
421 | |
422 | static const bool isRef = std::is_reference<T>::value; |
423 | |
424 | using wrap = ReferenceStorage<typename std::remove_reference<T>::type>; |
425 | |
426 | using error_type = std::unique_ptr<ErrorInfoBase>; |
427 | |
428 | public: |
429 | using storage_type = typename std::conditional<isRef, wrap, T>::type; |
430 | using value_type = T; |
431 | |
432 | private: |
433 | using reference = typename std::remove_reference<T>::type &; |
434 | using const_reference = const typename std::remove_reference<T>::type &; |
435 | using pointer = typename std::remove_reference<T>::type *; |
436 | using const_pointer = const typename std::remove_reference<T>::type *; |
437 | |
438 | public: |
439 | /// Create an Expected<T> error value from the given Error. |
440 | Expected(Error Err) |
441 | : HasError(true) |
442 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
443 | // Expected is unchecked upon construction in Debug builds. |
444 | , Unchecked(true) |
445 | #endif |
446 | { |
447 | assert(Err && "Cannot create Expected<T> from Error success value.")(static_cast <bool> (Err && "Cannot create Expected<T> from Error success value." ) ? void (0) : __assert_fail ("Err && \"Cannot create Expected<T> from Error success value.\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/Support/Error.h" , 447, __extension__ __PRETTY_FUNCTION__)); |
448 | new (getErrorStorage()) error_type(Err.takePayload()); |
449 | } |
450 | |
451 | /// Forbid to convert from Error::success() implicitly, this avoids having |
452 | /// Expected<T> foo() { return Error::success(); } which compiles otherwise |
453 | /// but triggers the assertion above. |
454 | Expected(ErrorSuccess) = delete; |
455 | |
456 | /// Create an Expected<T> success value from the given OtherT value, which |
457 | /// must be convertible to T. |
458 | template <typename OtherT> |
459 | Expected(OtherT &&Val, |
460 | typename std::enable_if<std::is_convertible<OtherT, T>::value>::type |
461 | * = nullptr) |
462 | : HasError(false) |
463 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
464 | // Expected is unchecked upon construction in Debug builds. |
465 | , Unchecked(true) |
466 | #endif |
467 | { |
468 | new (getStorage()) storage_type(std::forward<OtherT>(Val)); |
469 | } |
470 | |
471 | /// Move construct an Expected<T> value. |
472 | Expected(Expected &&Other) { moveConstruct(std::move(Other)); } |
473 | |
474 | /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT |
475 | /// must be convertible to T. |
476 | template <class OtherT> |
477 | Expected(Expected<OtherT> &&Other, |
478 | typename std::enable_if<std::is_convertible<OtherT, T>::value>::type |
479 | * = nullptr) { |
480 | moveConstruct(std::move(Other)); |
481 | } |
482 | |
483 | /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT |
484 | /// isn't convertible to T. |
485 | template <class OtherT> |
486 | explicit Expected( |
487 | Expected<OtherT> &&Other, |
488 | typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * = |
489 | nullptr) { |
490 | moveConstruct(std::move(Other)); |
491 | } |
492 | |
493 | /// Move-assign from another Expected<T>. |
494 | Expected &operator=(Expected &&Other) { |
495 | moveAssign(std::move(Other)); |
496 | return *this; |
497 | } |
498 | |
499 | /// Destroy an Expected<T>. |
500 | ~Expected() { |
501 | assertIsChecked(); |
502 | if (!HasError) |
503 | getStorage()->~storage_type(); |
504 | else |
505 | getErrorStorage()->~error_type(); |
506 | } |
507 | |
508 | /// \brief Return false if there is an error. |
509 | explicit operator bool() { |
510 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
511 | Unchecked = HasError; |
512 | #endif |
513 | return !HasError; |
514 | } |
515 | |
516 | /// \brief Returns a reference to the stored T value. |
517 | reference get() { |
518 | assertIsChecked(); |
519 | return *getStorage(); |
520 | } |
521 | |
522 | /// \brief Returns a const reference to the stored T value. |
523 | const_reference get() const { |
524 | assertIsChecked(); |
525 | return const_cast<Expected<T> *>(this)->get(); |
526 | } |
527 | |
528 | /// \brief Check that this Expected<T> is an error of type ErrT. |
529 | template <typename ErrT> bool errorIsA() const { |
530 | return HasError && (*getErrorStorage())->template isA<ErrT>(); |
531 | } |
532 | |
533 | /// \brief Take ownership of the stored error. |
534 | /// After calling this the Expected<T> is in an indeterminate state that can |
535 | /// only be safely destructed. No further calls (beside the destructor) should |
536 | /// be made on the Expected<T> vaule. |
537 | Error takeError() { |
538 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
539 | Unchecked = false; |
540 | #endif |
541 | return HasError ? Error(std::move(*getErrorStorage())) : Error::success(); |
542 | } |
543 | |
544 | /// \brief Returns a pointer to the stored T value. |
545 | pointer operator->() { |
546 | assertIsChecked(); |
547 | return toPointer(getStorage()); |
548 | } |
549 | |
550 | /// \brief Returns a const pointer to the stored T value. |
551 | const_pointer operator->() const { |
552 | assertIsChecked(); |
553 | return toPointer(getStorage()); |
554 | } |
555 | |
556 | /// \brief Returns a reference to the stored T value. |
557 | reference operator*() { |
558 | assertIsChecked(); |
559 | return *getStorage(); |
560 | } |
561 | |
562 | /// \brief Returns a const reference to the stored T value. |
563 | const_reference operator*() const { |
564 | assertIsChecked(); |
565 | return *getStorage(); |
566 | } |
567 | |
568 | private: |
569 | template <class T1> |
570 | static bool compareThisIfSameType(const T1 &a, const T1 &b) { |
571 | return &a == &b; |
572 | } |
573 | |
574 | template <class T1, class T2> |
575 | static bool compareThisIfSameType(const T1 &a, const T2 &b) { |
576 | return false; |
577 | } |
578 | |
579 | template <class OtherT> void moveConstruct(Expected<OtherT> &&Other) { |
580 | HasError = Other.HasError; |
581 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
582 | Unchecked = true; |
583 | Other.Unchecked = false; |
584 | #endif |
585 | |
586 | if (!HasError) |
587 | new (getStorage()) storage_type(std::move(*Other.getStorage())); |
588 | else |
589 | new (getErrorStorage()) error_type(std::move(*Other.getErrorStorage())); |
590 | } |
591 | |
592 | template <class OtherT> void moveAssign(Expected<OtherT> &&Other) { |
593 | assertIsChecked(); |
594 | |
595 | if (compareThisIfSameType(*this, Other)) |
596 | return; |
597 | |
598 | this->~Expected(); |
599 | new (this) Expected(std::move(Other)); |
600 | } |
601 | |
602 | pointer toPointer(pointer Val) { return Val; } |
603 | |
604 | const_pointer toPointer(const_pointer Val) const { return Val; } |
605 | |
606 | pointer toPointer(wrap *Val) { return &Val->get(); } |
607 | |
608 | const_pointer toPointer(const wrap *Val) const { return &Val->get(); } |
609 | |
610 | storage_type *getStorage() { |
611 | assert(!HasError && "Cannot get value when an error exists!")(static_cast <bool> (!HasError && "Cannot get value when an error exists!" ) ? void (0) : __assert_fail ("!HasError && \"Cannot get value when an error exists!\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/Support/Error.h" , 611, __extension__ __PRETTY_FUNCTION__)); |
612 | return reinterpret_cast<storage_type *>(TStorage.buffer); |
613 | } |
614 | |
615 | const storage_type *getStorage() const { |
616 | assert(!HasError && "Cannot get value when an error exists!")(static_cast <bool> (!HasError && "Cannot get value when an error exists!" ) ? void (0) : __assert_fail ("!HasError && \"Cannot get value when an error exists!\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/Support/Error.h" , 616, __extension__ __PRETTY_FUNCTION__)); |
617 | return reinterpret_cast<const storage_type *>(TStorage.buffer); |
618 | } |
619 | |
620 | error_type *getErrorStorage() { |
621 | assert(HasError && "Cannot get error when a value exists!")(static_cast <bool> (HasError && "Cannot get error when a value exists!" ) ? void (0) : __assert_fail ("HasError && \"Cannot get error when a value exists!\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/Support/Error.h" , 621, __extension__ __PRETTY_FUNCTION__)); |
622 | return reinterpret_cast<error_type *>(ErrorStorage.buffer); |
623 | } |
624 | |
625 | const error_type *getErrorStorage() const { |
626 | assert(HasError && "Cannot get error when a value exists!")(static_cast <bool> (HasError && "Cannot get error when a value exists!" ) ? void (0) : __assert_fail ("HasError && \"Cannot get error when a value exists!\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/Support/Error.h" , 626, __extension__ __PRETTY_FUNCTION__)); |
627 | return reinterpret_cast<const error_type *>(ErrorStorage.buffer); |
628 | } |
629 | |
630 | // Used by ExpectedAsOutParameter to reset the checked flag. |
631 | void setUnchecked() { |
632 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
633 | Unchecked = true; |
634 | #endif |
635 | } |
636 | |
637 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
638 | LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) |
639 | LLVM_ATTRIBUTE_NOINLINE__attribute__((noinline)) |
640 | void fatalUncheckedExpected() const { |
641 | dbgs() << "Expected<T> must be checked before access or destruction.\n"; |
642 | if (HasError) { |
643 | dbgs() << "Unchecked Expected<T> contained error:\n"; |
644 | (*getErrorStorage())->log(dbgs()); |
645 | } else |
646 | dbgs() << "Expected<T> value was in success state. (Note: Expected<T> " |
647 | "values in success mode must still be checked prior to being " |
648 | "destroyed).\n"; |
649 | abort(); |
650 | } |
651 | #endif |
652 | |
653 | void assertIsChecked() { |
654 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
655 | if (LLVM_UNLIKELY(Unchecked)__builtin_expect((bool)(Unchecked), false)) |
656 | fatalUncheckedExpected(); |
657 | #endif |
658 | } |
659 | |
660 | union { |
661 | AlignedCharArrayUnion<storage_type> TStorage; |
662 | AlignedCharArrayUnion<error_type> ErrorStorage; |
663 | }; |
664 | bool HasError : 1; |
665 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
666 | bool Unchecked : 1; |
667 | #endif |
668 | }; |
669 | |
670 | /// Report a serious error, calling any installed error handler. See |
671 | /// ErrorHandling.h. |
672 | LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) void report_fatal_error(Error Err, |
673 | bool gen_crash_diag = true); |
674 | |
675 | /// Report a fatal error if Err is a failure value. |
676 | /// |
677 | /// This function can be used to wrap calls to fallible functions ONLY when it |
678 | /// is known that the Error will always be a success value. E.g. |
679 | /// |
680 | /// @code{.cpp} |
681 | /// // foo only attempts the fallible operation if DoFallibleOperation is |
682 | /// // true. If DoFallibleOperation is false then foo always returns |
683 | /// // Error::success(). |
684 | /// Error foo(bool DoFallibleOperation); |
685 | /// |
686 | /// cantFail(foo(false)); |
687 | /// @endcode |
688 | inline void cantFail(Error Err, const char *Msg = nullptr) { |
689 | if (Err) { |
690 | if (!Msg) |
691 | Msg = "Failure value returned from cantFail wrapped call"; |
692 | llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/Support/Error.h" , 692); |
693 | } |
694 | } |
695 | |
696 | /// Report a fatal error if ValOrErr is a failure value, otherwise unwraps and |
697 | /// returns the contained value. |
698 | /// |
699 | /// This function can be used to wrap calls to fallible functions ONLY when it |
700 | /// is known that the Error will always be a success value. E.g. |
701 | /// |
702 | /// @code{.cpp} |
703 | /// // foo only attempts the fallible operation if DoFallibleOperation is |
704 | /// // true. If DoFallibleOperation is false then foo always returns an int. |
705 | /// Expected<int> foo(bool DoFallibleOperation); |
706 | /// |
707 | /// int X = cantFail(foo(false)); |
708 | /// @endcode |
709 | template <typename T> |
710 | T cantFail(Expected<T> ValOrErr, const char *Msg = nullptr) { |
711 | if (ValOrErr) |
712 | return std::move(*ValOrErr); |
713 | else { |
714 | if (!Msg) |
715 | Msg = "Failure value returned from cantFail wrapped call"; |
716 | llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/Support/Error.h" , 716); |
717 | } |
718 | } |
719 | |
720 | /// Report a fatal error if ValOrErr is a failure value, otherwise unwraps and |
721 | /// returns the contained reference. |
722 | /// |
723 | /// This function can be used to wrap calls to fallible functions ONLY when it |
724 | /// is known that the Error will always be a success value. E.g. |
725 | /// |
726 | /// @code{.cpp} |
727 | /// // foo only attempts the fallible operation if DoFallibleOperation is |
728 | /// // true. If DoFallibleOperation is false then foo always returns a Bar&. |
729 | /// Expected<Bar&> foo(bool DoFallibleOperation); |
730 | /// |
731 | /// Bar &X = cantFail(foo(false)); |
732 | /// @endcode |
733 | template <typename T> |
734 | T& cantFail(Expected<T&> ValOrErr, const char *Msg = nullptr) { |
735 | if (ValOrErr) |
736 | return *ValOrErr; |
737 | else { |
738 | if (!Msg) |
739 | Msg = "Failure value returned from cantFail wrapped call"; |
740 | llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/Support/Error.h" , 740); |
741 | } |
742 | } |
743 | |
744 | /// Helper for testing applicability of, and applying, handlers for |
745 | /// ErrorInfo types. |
746 | template <typename HandlerT> |
747 | class ErrorHandlerTraits |
748 | : public ErrorHandlerTraits<decltype( |
749 | &std::remove_reference<HandlerT>::type::operator())> {}; |
750 | |
751 | // Specialization functions of the form 'Error (const ErrT&)'. |
752 | template <typename ErrT> class ErrorHandlerTraits<Error (&)(ErrT &)> { |
753 | public: |
754 | static bool appliesTo(const ErrorInfoBase &E) { |
755 | return E.template isA<ErrT>(); |
756 | } |
757 | |
758 | template <typename HandlerT> |
759 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { |
760 | assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler" ) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/Support/Error.h" , 760, __extension__ __PRETTY_FUNCTION__)); |
761 | return H(static_cast<ErrT &>(*E)); |
762 | } |
763 | }; |
764 | |
765 | // Specialization functions of the form 'void (const ErrT&)'. |
766 | template <typename ErrT> class ErrorHandlerTraits<void (&)(ErrT &)> { |
767 | public: |
768 | static bool appliesTo(const ErrorInfoBase &E) { |
769 | return E.template isA<ErrT>(); |
770 | } |
771 | |
772 | template <typename HandlerT> |
773 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { |
774 | assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler" ) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/Support/Error.h" , 774, __extension__ __PRETTY_FUNCTION__)); |
775 | H(static_cast<ErrT &>(*E)); |
776 | return Error::success(); |
777 | } |
778 | }; |
779 | |
780 | /// Specialization for functions of the form 'Error (std::unique_ptr<ErrT>)'. |
781 | template <typename ErrT> |
782 | class ErrorHandlerTraits<Error (&)(std::unique_ptr<ErrT>)> { |
783 | public: |
784 | static bool appliesTo(const ErrorInfoBase &E) { |
785 | return E.template isA<ErrT>(); |
786 | } |
787 | |
788 | template <typename HandlerT> |
789 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { |
790 | assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler" ) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/Support/Error.h" , 790, __extension__ __PRETTY_FUNCTION__)); |
791 | std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release())); |
792 | return H(std::move(SubE)); |
793 | } |
794 | }; |
795 | |
796 | /// Specialization for functions of the form 'void (std::unique_ptr<ErrT>)'. |
797 | template <typename ErrT> |
798 | class ErrorHandlerTraits<void (&)(std::unique_ptr<ErrT>)> { |
799 | public: |
800 | static bool appliesTo(const ErrorInfoBase &E) { |
801 | return E.template isA<ErrT>(); |
802 | } |
803 | |
804 | template <typename HandlerT> |
805 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { |
806 | assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler" ) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/Support/Error.h" , 806, __extension__ __PRETTY_FUNCTION__)); |
807 | std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release())); |
808 | H(std::move(SubE)); |
809 | return Error::success(); |
810 | } |
811 | }; |
812 | |
813 | // Specialization for member functions of the form 'RetT (const ErrT&)'. |
814 | template <typename C, typename RetT, typename ErrT> |
815 | class ErrorHandlerTraits<RetT (C::*)(ErrT &)> |
816 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; |
817 | |
818 | // Specialization for member functions of the form 'RetT (const ErrT&) const'. |
819 | template <typename C, typename RetT, typename ErrT> |
820 | class ErrorHandlerTraits<RetT (C::*)(ErrT &) const> |
821 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; |
822 | |
823 | // Specialization for member functions of the form 'RetT (const ErrT&)'. |
824 | template <typename C, typename RetT, typename ErrT> |
825 | class ErrorHandlerTraits<RetT (C::*)(const ErrT &)> |
826 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; |
827 | |
828 | // Specialization for member functions of the form 'RetT (const ErrT&) const'. |
829 | template <typename C, typename RetT, typename ErrT> |
830 | class ErrorHandlerTraits<RetT (C::*)(const ErrT &) const> |
831 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; |
832 | |
833 | /// Specialization for member functions of the form |
834 | /// 'RetT (std::unique_ptr<ErrT>)'. |
835 | template <typename C, typename RetT, typename ErrT> |
836 | class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>)> |
837 | : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {}; |
838 | |
839 | /// Specialization for member functions of the form |
840 | /// 'RetT (std::unique_ptr<ErrT>) const'. |
841 | template <typename C, typename RetT, typename ErrT> |
842 | class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>) const> |
843 | : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {}; |
844 | |
845 | inline Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload) { |
846 | return Error(std::move(Payload)); |
847 | } |
848 | |
849 | template <typename HandlerT, typename... HandlerTs> |
850 | Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload, |
851 | HandlerT &&Handler, HandlerTs &&... Handlers) { |
852 | if (ErrorHandlerTraits<HandlerT>::appliesTo(*Payload)) |
853 | return ErrorHandlerTraits<HandlerT>::apply(std::forward<HandlerT>(Handler), |
854 | std::move(Payload)); |
855 | return handleErrorImpl(std::move(Payload), |
856 | std::forward<HandlerTs>(Handlers)...); |
857 | } |
858 | |
859 | /// Pass the ErrorInfo(s) contained in E to their respective handlers. Any |
860 | /// unhandled errors (or Errors returned by handlers) are re-concatenated and |
861 | /// returned. |
862 | /// Because this function returns an error, its result must also be checked |
863 | /// or returned. If you intend to handle all errors use handleAllErrors |
864 | /// (which returns void, and will abort() on unhandled errors) instead. |
865 | template <typename... HandlerTs> |
866 | Error handleErrors(Error E, HandlerTs &&... Hs) { |
867 | if (!E) |
868 | return Error::success(); |
869 | |
870 | std::unique_ptr<ErrorInfoBase> Payload = E.takePayload(); |
871 | |
872 | if (Payload->isA<ErrorList>()) { |
873 | ErrorList &List = static_cast<ErrorList &>(*Payload); |
874 | Error R; |
875 | for (auto &P : List.Payloads) |
876 | R = ErrorList::join( |
877 | std::move(R), |
878 | handleErrorImpl(std::move(P), std::forward<HandlerTs>(Hs)...)); |
879 | return R; |
880 | } |
881 | |
882 | return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...); |
883 | } |
884 | |
885 | /// Behaves the same as handleErrors, except that it requires that all |
886 | /// errors be handled by the given handlers. If any unhandled error remains |
887 | /// after the handlers have run, report_fatal_error() will be called. |
888 | template <typename... HandlerTs> |
889 | void handleAllErrors(Error E, HandlerTs &&... Handlers) { |
890 | cantFail(handleErrors(std::move(E), std::forward<HandlerTs>(Handlers)...)); |
891 | } |
892 | |
893 | /// Check that E is a non-error, then drop it. |
894 | /// If E is an error report_fatal_error will be called. |
895 | inline void handleAllErrors(Error E) { |
896 | cantFail(std::move(E)); |
897 | } |
898 | |
899 | /// Handle any errors (if present) in an Expected<T>, then try a recovery path. |
900 | /// |
901 | /// If the incoming value is a success value it is returned unmodified. If it |
902 | /// is a failure value then it the contained error is passed to handleErrors. |
903 | /// If handleErrors is able to handle the error then the RecoveryPath functor |
904 | /// is called to supply the final result. If handleErrors is not able to |
905 | /// handle all errors then the unhandled errors are returned. |
906 | /// |
907 | /// This utility enables the follow pattern: |
908 | /// |
909 | /// @code{.cpp} |
910 | /// enum FooStrategy { Aggressive, Conservative }; |
911 | /// Expected<Foo> foo(FooStrategy S); |
912 | /// |
913 | /// auto ResultOrErr = |
914 | /// handleExpected( |
915 | /// foo(Aggressive), |
916 | /// []() { return foo(Conservative); }, |
917 | /// [](AggressiveStrategyError&) { |
918 | /// // Implicitly conusme this - we'll recover by using a conservative |
919 | /// // strategy. |
920 | /// }); |
921 | /// |
922 | /// @endcode |
923 | template <typename T, typename RecoveryFtor, typename... HandlerTs> |
924 | Expected<T> handleExpected(Expected<T> ValOrErr, RecoveryFtor &&RecoveryPath, |
925 | HandlerTs &&... Handlers) { |
926 | if (ValOrErr) |
927 | return ValOrErr; |
928 | |
929 | if (auto Err = handleErrors(ValOrErr.takeError(), |
930 | std::forward<HandlerTs>(Handlers)...)) |
931 | return std::move(Err); |
932 | |
933 | return RecoveryPath(); |
934 | } |
935 | |
936 | /// Log all errors (if any) in E to OS. If there are any errors, ErrorBanner |
937 | /// will be printed before the first one is logged. A newline will be printed |
938 | /// after each error. |
939 | /// |
940 | /// This is useful in the base level of your program to allow clean termination |
941 | /// (allowing clean deallocation of resources, etc.), while reporting error |
942 | /// information to the user. |
943 | void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner); |
944 | |
945 | /// Write all error messages (if any) in E to a string. The newline character |
946 | /// is used to separate error messages. |
947 | inline std::string toString(Error E) { |
948 | SmallVector<std::string, 2> Errors; |
949 | handleAllErrors(std::move(E), [&Errors](const ErrorInfoBase &EI) { |
950 | Errors.push_back(EI.message()); |
951 | }); |
952 | return join(Errors.begin(), Errors.end(), "\n"); |
953 | } |
954 | |
955 | /// Consume a Error without doing anything. This method should be used |
956 | /// only where an error can be considered a reasonable and expected return |
957 | /// value. |
958 | /// |
959 | /// Uses of this method are potentially indicative of design problems: If it's |
960 | /// legitimate to do nothing while processing an "error", the error-producer |
961 | /// might be more clearly refactored to return an Optional<T>. |
962 | inline void consumeError(Error Err) { |
963 | handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {}); |
964 | } |
965 | |
966 | /// Helper for converting an Error to a bool. |
967 | /// |
968 | /// This method returns true if Err is in an error state, or false if it is |
969 | /// in a success state. Puts Err in a checked state in both cases (unlike |
970 | /// Error::operator bool(), which only does this for success states). |
971 | inline bool errorToBool(Error Err) { |
972 | bool IsError = static_cast<bool>(Err); |
973 | if (IsError) |
974 | consumeError(std::move(Err)); |
975 | return IsError; |
976 | } |
977 | |
978 | /// Helper for Errors used as out-parameters. |
979 | /// |
980 | /// This helper is for use with the Error-as-out-parameter idiom, where an error |
981 | /// is passed to a function or method by reference, rather than being returned. |
982 | /// In such cases it is helpful to set the checked bit on entry to the function |
983 | /// so that the error can be written to (unchecked Errors abort on assignment) |
984 | /// and clear the checked bit on exit so that clients cannot accidentally forget |
985 | /// to check the result. This helper performs these actions automatically using |
986 | /// RAII: |
987 | /// |
988 | /// @code{.cpp} |
989 | /// Result foo(Error &Err) { |
990 | /// ErrorAsOutParameter ErrAsOutParam(&Err); // 'Checked' flag set |
991 | /// // <body of foo> |
992 | /// // <- 'Checked' flag auto-cleared when ErrAsOutParam is destructed. |
993 | /// } |
994 | /// @endcode |
995 | /// |
996 | /// ErrorAsOutParameter takes an Error* rather than Error& so that it can be |
997 | /// used with optional Errors (Error pointers that are allowed to be null). If |
998 | /// ErrorAsOutParameter took an Error reference, an instance would have to be |
999 | /// created inside every condition that verified that Error was non-null. By |
1000 | /// taking an Error pointer we can just create one instance at the top of the |
1001 | /// function. |
1002 | class ErrorAsOutParameter { |
1003 | public: |
1004 | ErrorAsOutParameter(Error *Err) : Err(Err) { |
1005 | // Raise the checked bit if Err is success. |
1006 | if (Err) |
1007 | (void)!!*Err; |
1008 | } |
1009 | |
1010 | ~ErrorAsOutParameter() { |
1011 | // Clear the checked bit. |
1012 | if (Err && !*Err) |
1013 | *Err = Error::success(); |
1014 | } |
1015 | |
1016 | private: |
1017 | Error *Err; |
1018 | }; |
1019 | |
1020 | /// Helper for Expected<T>s used as out-parameters. |
1021 | /// |
1022 | /// See ErrorAsOutParameter. |
1023 | template <typename T> |
1024 | class ExpectedAsOutParameter { |
1025 | public: |
1026 | ExpectedAsOutParameter(Expected<T> *ValOrErr) |
1027 | : ValOrErr(ValOrErr) { |
1028 | if (ValOrErr) |
1029 | (void)!!*ValOrErr; |
1030 | } |
1031 | |
1032 | ~ExpectedAsOutParameter() { |
1033 | if (ValOrErr) |
1034 | ValOrErr->setUnchecked(); |
1035 | } |
1036 | |
1037 | private: |
1038 | Expected<T> *ValOrErr; |
1039 | }; |
1040 | |
1041 | /// This class wraps a std::error_code in a Error. |
1042 | /// |
1043 | /// This is useful if you're writing an interface that returns a Error |
1044 | /// (or Expected) and you want to call code that still returns |
1045 | /// std::error_codes. |
1046 | class ECError : public ErrorInfo<ECError> { |
1047 | friend Error errorCodeToError(std::error_code); |
1048 | |
1049 | public: |
1050 | void setErrorCode(std::error_code EC) { this->EC = EC; } |
1051 | std::error_code convertToErrorCode() const override { return EC; } |
1052 | void log(raw_ostream &OS) const override { OS << EC.message(); } |
1053 | |
1054 | // Used by ErrorInfo::classID. |
1055 | static char ID; |
1056 | |
1057 | protected: |
1058 | ECError() = default; |
1059 | ECError(std::error_code EC) : EC(EC) {} |
1060 | |
1061 | std::error_code EC; |
1062 | }; |
1063 | |
1064 | /// The value returned by this function can be returned from convertToErrorCode |
1065 | /// for Error values where no sensible translation to std::error_code exists. |
1066 | /// It should only be used in this situation, and should never be used where a |
1067 | /// sensible conversion to std::error_code is available, as attempts to convert |
1068 | /// to/from this error will result in a fatal error. (i.e. it is a programmatic |
1069 | ///error to try to convert such a value). |
1070 | std::error_code inconvertibleErrorCode(); |
1071 | |
1072 | /// Helper for converting an std::error_code to a Error. |
1073 | Error errorCodeToError(std::error_code EC); |
1074 | |
1075 | /// Helper for converting an ECError to a std::error_code. |
1076 | /// |
1077 | /// This method requires that Err be Error() or an ECError, otherwise it |
1078 | /// will trigger a call to abort(). |
1079 | std::error_code errorToErrorCode(Error Err); |
1080 | |
1081 | /// Convert an ErrorOr<T> to an Expected<T>. |
1082 | template <typename T> Expected<T> errorOrToExpected(ErrorOr<T> &&EO) { |
1083 | if (auto EC = EO.getError()) |
1084 | return errorCodeToError(EC); |
1085 | return std::move(*EO); |
1086 | } |
1087 | |
1088 | /// Convert an Expected<T> to an ErrorOr<T>. |
1089 | template <typename T> ErrorOr<T> expectedToErrorOr(Expected<T> &&E) { |
1090 | if (auto Err = E.takeError()) |
1091 | return errorToErrorCode(std::move(Err)); |
1092 | return std::move(*E); |
1093 | } |
1094 | |
1095 | /// This class wraps a string in an Error. |
1096 | /// |
1097 | /// StringError is useful in cases where the client is not expected to be able |
1098 | /// to consume the specific error message programmatically (for example, if the |
1099 | /// error message is to be presented to the user). |
1100 | class StringError : public ErrorInfo<StringError> { |
1101 | public: |
1102 | static char ID; |
1103 | |
1104 | StringError(const Twine &S, std::error_code EC); |
1105 | |
1106 | void log(raw_ostream &OS) const override; |
1107 | std::error_code convertToErrorCode() const override; |
1108 | |
1109 | const std::string &getMessage() const { return Msg; } |
1110 | |
1111 | private: |
1112 | std::string Msg; |
1113 | std::error_code EC; |
1114 | }; |
1115 | |
1116 | /// Helper for check-and-exit error handling. |
1117 | /// |
1118 | /// For tool use only. NOT FOR USE IN LIBRARY CODE. |
1119 | /// |
1120 | class ExitOnError { |
1121 | public: |
1122 | /// Create an error on exit helper. |
1123 | ExitOnError(std::string Banner = "", int DefaultErrorExitCode = 1) |
1124 | : Banner(std::move(Banner)), |
1125 | GetExitCode([=](const Error &) { return DefaultErrorExitCode; }) {} |
1126 | |
1127 | /// Set the banner string for any errors caught by operator(). |
1128 | void setBanner(std::string Banner) { this->Banner = std::move(Banner); } |
1129 | |
1130 | /// Set the exit-code mapper function. |
1131 | void setExitCodeMapper(std::function<int(const Error &)> GetExitCode) { |
1132 | this->GetExitCode = std::move(GetExitCode); |
1133 | } |
1134 | |
1135 | /// Check Err. If it's in a failure state log the error(s) and exit. |
1136 | void operator()(Error Err) const { checkError(std::move(Err)); } |
1137 | |
1138 | /// Check E. If it's in a success state then return the contained value. If |
1139 | /// it's in a failure state log the error(s) and exit. |
1140 | template <typename T> T operator()(Expected<T> &&E) const { |
1141 | checkError(E.takeError()); |
1142 | return std::move(*E); |
1143 | } |
1144 | |
1145 | /// Check E. If it's in a success state then return the contained reference. If |
1146 | /// it's in a failure state log the error(s) and exit. |
1147 | template <typename T> T& operator()(Expected<T&> &&E) const { |
1148 | checkError(E.takeError()); |
1149 | return *E; |
1150 | } |
1151 | |
1152 | private: |
1153 | void checkError(Error Err) const { |
1154 | if (Err) { |
1155 | int ExitCode = GetExitCode(Err); |
1156 | logAllUnhandledErrors(std::move(Err), errs(), Banner); |
1157 | exit(ExitCode); |
1158 | } |
1159 | } |
1160 | |
1161 | std::string Banner; |
1162 | std::function<int(const Error &)> GetExitCode; |
1163 | }; |
1164 | |
1165 | } // end namespace llvm |
1166 | |
1167 | #endif // LLVM_SUPPORT_ERROR_H |
1 | //===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- C++ -*-===// |
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 some templates that are useful if you are working with the |
11 | // STL at all. |
12 | // |
13 | // No library is required when using these functions. |
14 | // |
15 | //===----------------------------------------------------------------------===// |
16 | |
17 | #ifndef LLVM_ADT_STLEXTRAS_H |
18 | #define LLVM_ADT_STLEXTRAS_H |
19 | |
20 | #include "llvm/ADT/Optional.h" |
21 | #include "llvm/ADT/SmallVector.h" |
22 | #include "llvm/ADT/iterator.h" |
23 | #include "llvm/ADT/iterator_range.h" |
24 | #include "llvm/Support/ErrorHandling.h" |
25 | #include <algorithm> |
26 | #include <cassert> |
27 | #include <cstddef> |
28 | #include <cstdint> |
29 | #include <cstdlib> |
30 | #include <functional> |
31 | #include <initializer_list> |
32 | #include <iterator> |
33 | #include <limits> |
34 | #include <memory> |
35 | #include <tuple> |
36 | #include <type_traits> |
37 | #include <utility> |
38 | |
39 | namespace llvm { |
40 | |
41 | // Only used by compiler if both template types are the same. Useful when |
42 | // using SFINAE to test for the existence of member functions. |
43 | template <typename T, T> struct SameType; |
44 | |
45 | namespace detail { |
46 | |
47 | template <typename RangeT> |
48 | using IterOfRange = decltype(std::begin(std::declval<RangeT &>())); |
49 | |
50 | template <typename RangeT> |
51 | using ValueOfRange = typename std::remove_reference<decltype( |
52 | *std::begin(std::declval<RangeT &>()))>::type; |
53 | |
54 | } // end namespace detail |
55 | |
56 | //===----------------------------------------------------------------------===// |
57 | // Extra additions to <functional> |
58 | //===----------------------------------------------------------------------===// |
59 | |
60 | template <class Ty> struct identity { |
61 | using argument_type = Ty; |
62 | |
63 | Ty &operator()(Ty &self) const { |
64 | return self; |
65 | } |
66 | const Ty &operator()(const Ty &self) const { |
67 | return self; |
68 | } |
69 | }; |
70 | |
71 | template <class Ty> struct less_ptr { |
72 | bool operator()(const Ty* left, const Ty* right) const { |
73 | return *left < *right; |
74 | } |
75 | }; |
76 | |
77 | template <class Ty> struct greater_ptr { |
78 | bool operator()(const Ty* left, const Ty* right) const { |
79 | return *right < *left; |
80 | } |
81 | }; |
82 | |
83 | /// An efficient, type-erasing, non-owning reference to a callable. This is |
84 | /// intended for use as the type of a function parameter that is not used |
85 | /// after the function in question returns. |
86 | /// |
87 | /// This class does not own the callable, so it is not in general safe to store |
88 | /// a function_ref. |
89 | template<typename Fn> class function_ref; |
90 | |
91 | template<typename Ret, typename ...Params> |
92 | class function_ref<Ret(Params...)> { |
93 | Ret (*callback)(intptr_t callable, Params ...params) = nullptr; |
94 | intptr_t callable; |
95 | |
96 | template<typename Callable> |
97 | static Ret callback_fn(intptr_t callable, Params ...params) { |
98 | return (*reinterpret_cast<Callable*>(callable))( |
99 | std::forward<Params>(params)...); |
100 | } |
101 | |
102 | public: |
103 | function_ref() = default; |
104 | function_ref(std::nullptr_t) {} |
105 | |
106 | template <typename Callable> |
107 | function_ref(Callable &&callable, |
108 | typename std::enable_if< |
109 | !std::is_same<typename std::remove_reference<Callable>::type, |
110 | function_ref>::value>::type * = nullptr) |
111 | : callback(callback_fn<typename std::remove_reference<Callable>::type>), |
112 | callable(reinterpret_cast<intptr_t>(&callable)) {} |
113 | |
114 | Ret operator()(Params ...params) const { |
115 | return callback(callable, std::forward<Params>(params)...); |
116 | } |
117 | |
118 | operator bool() const { return callback; } |
119 | }; |
120 | |
121 | // deleter - Very very very simple method that is used to invoke operator |
122 | // delete on something. It is used like this: |
123 | // |
124 | // for_each(V.begin(), B.end(), deleter<Interval>); |
125 | template <class T> |
126 | inline void deleter(T *Ptr) { |
127 | delete Ptr; |
128 | } |
129 | |
130 | //===----------------------------------------------------------------------===// |
131 | // Extra additions to <iterator> |
132 | //===----------------------------------------------------------------------===// |
133 | |
134 | namespace adl_detail { |
135 | |
136 | using std::begin; |
137 | |
138 | template <typename ContainerTy> |
139 | auto adl_begin(ContainerTy &&container) |
140 | -> decltype(begin(std::forward<ContainerTy>(container))) { |
141 | return begin(std::forward<ContainerTy>(container)); |
142 | } |
143 | |
144 | using std::end; |
145 | |
146 | template <typename ContainerTy> |
147 | auto adl_end(ContainerTy &&container) |
148 | -> decltype(end(std::forward<ContainerTy>(container))) { |
149 | return end(std::forward<ContainerTy>(container)); |
150 | } |
151 | |
152 | using std::swap; |
153 | |
154 | template <typename T> |
155 | void adl_swap(T &&lhs, T &&rhs) noexcept(noexcept(swap(std::declval<T>(), |
156 | std::declval<T>()))) { |
157 | swap(std::forward<T>(lhs), std::forward<T>(rhs)); |
158 | } |
159 | |
160 | } // end namespace adl_detail |
161 | |
162 | template <typename ContainerTy> |
163 | auto adl_begin(ContainerTy &&container) |
164 | -> decltype(adl_detail::adl_begin(std::forward<ContainerTy>(container))) { |
165 | return adl_detail::adl_begin(std::forward<ContainerTy>(container)); |
166 | } |
167 | |
168 | template <typename ContainerTy> |
169 | auto adl_end(ContainerTy &&container) |
170 | -> decltype(adl_detail::adl_end(std::forward<ContainerTy>(container))) { |
171 | return adl_detail::adl_end(std::forward<ContainerTy>(container)); |
172 | } |
173 | |
174 | template <typename T> |
175 | void adl_swap(T &&lhs, T &&rhs) noexcept( |
176 | noexcept(adl_detail::adl_swap(std::declval<T>(), std::declval<T>()))) { |
177 | adl_detail::adl_swap(std::forward<T>(lhs), std::forward<T>(rhs)); |
178 | } |
179 | |
180 | // mapped_iterator - This is a simple iterator adapter that causes a function to |
181 | // be applied whenever operator* is invoked on the iterator. |
182 | |
183 | template <typename ItTy, typename FuncTy, |
184 | typename FuncReturnTy = |
185 | decltype(std::declval<FuncTy>()(*std::declval<ItTy>()))> |
186 | class mapped_iterator |
187 | : public iterator_adaptor_base< |
188 | mapped_iterator<ItTy, FuncTy>, ItTy, |
189 | typename std::iterator_traits<ItTy>::iterator_category, |
190 | typename std::remove_reference<FuncReturnTy>::type> { |
191 | public: |
192 | mapped_iterator(ItTy U, FuncTy F) |
193 | : mapped_iterator::iterator_adaptor_base(std::move(U)), F(std::move(F)) {} |
194 | |
195 | ItTy getCurrent() { return this->I; } |
196 | |
197 | FuncReturnTy operator*() { return F(*this->I); } |
198 | |
199 | private: |
200 | FuncTy F; |
201 | }; |
202 | |
203 | // map_iterator - Provide a convenient way to create mapped_iterators, just like |
204 | // make_pair is useful for creating pairs... |
205 | template <class ItTy, class FuncTy> |
206 | inline mapped_iterator<ItTy, FuncTy> map_iterator(ItTy I, FuncTy F) { |
207 | return mapped_iterator<ItTy, FuncTy>(std::move(I), std::move(F)); |
208 | } |
209 | |
210 | /// Helper to determine if type T has a member called rbegin(). |
211 | template <typename Ty> class has_rbegin_impl { |
212 | using yes = char[1]; |
213 | using no = char[2]; |
214 | |
215 | template <typename Inner> |
216 | static yes& test(Inner *I, decltype(I->rbegin()) * = nullptr); |
217 | |
218 | template <typename> |
219 | static no& test(...); |
220 | |
221 | public: |
222 | static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes); |
223 | }; |
224 | |
225 | /// Metafunction to determine if T& or T has a member called rbegin(). |
226 | template <typename Ty> |
227 | struct has_rbegin : has_rbegin_impl<typename std::remove_reference<Ty>::type> { |
228 | }; |
229 | |
230 | // Returns an iterator_range over the given container which iterates in reverse. |
231 | // Note that the container must have rbegin()/rend() methods for this to work. |
232 | template <typename ContainerTy> |
233 | auto reverse(ContainerTy &&C, |
234 | typename std::enable_if<has_rbegin<ContainerTy>::value>::type * = |
235 | nullptr) -> decltype(make_range(C.rbegin(), C.rend())) { |
236 | return make_range(C.rbegin(), C.rend()); |
237 | } |
238 | |
239 | // Returns a std::reverse_iterator wrapped around the given iterator. |
240 | template <typename IteratorTy> |
241 | std::reverse_iterator<IteratorTy> make_reverse_iterator(IteratorTy It) { |
242 | return std::reverse_iterator<IteratorTy>(It); |
243 | } |
244 | |
245 | // Returns an iterator_range over the given container which iterates in reverse. |
246 | // Note that the container must have begin()/end() methods which return |
247 | // bidirectional iterators for this to work. |
248 | template <typename ContainerTy> |
249 | auto reverse( |
250 | ContainerTy &&C, |
251 | typename std::enable_if<!has_rbegin<ContainerTy>::value>::type * = nullptr) |
252 | -> decltype(make_range(llvm::make_reverse_iterator(std::end(C)), |
253 | llvm::make_reverse_iterator(std::begin(C)))) { |
254 | return make_range(llvm::make_reverse_iterator(std::end(C)), |
255 | llvm::make_reverse_iterator(std::begin(C))); |
256 | } |
257 | |
258 | /// An iterator adaptor that filters the elements of given inner iterators. |
259 | /// |
260 | /// The predicate parameter should be a callable object that accepts the wrapped |
261 | /// iterator's reference type and returns a bool. When incrementing or |
262 | /// decrementing the iterator, it will call the predicate on each element and |
263 | /// skip any where it returns false. |
264 | /// |
265 | /// \code |
266 | /// int A[] = { 1, 2, 3, 4 }; |
267 | /// auto R = make_filter_range(A, [](int N) { return N % 2 == 1; }); |
268 | /// // R contains { 1, 3 }. |
269 | /// \endcode |
270 | template <typename WrappedIteratorT, typename PredicateT> |
271 | class filter_iterator |
272 | : public iterator_adaptor_base< |
273 | filter_iterator<WrappedIteratorT, PredicateT>, WrappedIteratorT, |
274 | typename std::common_type< |
275 | std::forward_iterator_tag, |
276 | typename std::iterator_traits< |
277 | WrappedIteratorT>::iterator_category>::type> { |
278 | using BaseT = iterator_adaptor_base< |
279 | filter_iterator<WrappedIteratorT, PredicateT>, WrappedIteratorT, |
280 | typename std::common_type< |
281 | std::forward_iterator_tag, |
282 | typename std::iterator_traits<WrappedIteratorT>::iterator_category>:: |
283 | type>; |
284 | |
285 | struct PayloadType { |
286 | WrappedIteratorT End; |
287 | PredicateT Pred; |
288 | }; |
289 | |
290 | Optional<PayloadType> Payload; |
291 | |
292 | void findNextValid() { |
293 | assert(Payload && "Payload should be engaged when findNextValid is called")(static_cast <bool> (Payload && "Payload should be engaged when findNextValid is called" ) ? void (0) : __assert_fail ("Payload && \"Payload should be engaged when findNextValid is called\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/ADT/STLExtras.h" , 293, __extension__ __PRETTY_FUNCTION__)); |
294 | while (this->I != Payload->End && !Payload->Pred(*this->I)) |
295 | BaseT::operator++(); |
296 | } |
297 | |
298 | // Construct the begin iterator. The begin iterator requires to know where end |
299 | // is, so that it can properly stop when it hits end. |
300 | filter_iterator(WrappedIteratorT Begin, WrappedIteratorT End, PredicateT Pred) |
301 | : BaseT(std::move(Begin)), |
302 | Payload(PayloadType{std::move(End), std::move(Pred)}) { |
303 | findNextValid(); |
304 | } |
305 | |
306 | // Construct the end iterator. It's not incrementable, so Payload doesn't |
307 | // have to be engaged. |
308 | filter_iterator(WrappedIteratorT End) : BaseT(End) {} |
309 | |
310 | public: |
311 | using BaseT::operator++; |
312 | |
313 | filter_iterator &operator++() { |
314 | BaseT::operator++(); |
315 | findNextValid(); |
316 | return *this; |
317 | } |
318 | |
319 | template <typename RT, typename PT> |
320 | friend iterator_range<filter_iterator<detail::IterOfRange<RT>, PT>> |
321 | make_filter_range(RT &&, PT); |
322 | }; |
323 | |
324 | /// Convenience function that takes a range of elements and a predicate, |
325 | /// and return a new filter_iterator range. |
326 | /// |
327 | /// FIXME: Currently if RangeT && is a rvalue reference to a temporary, the |
328 | /// lifetime of that temporary is not kept by the returned range object, and the |
329 | /// temporary is going to be dropped on the floor after the make_iterator_range |
330 | /// full expression that contains this function call. |
331 | template <typename RangeT, typename PredicateT> |
332 | iterator_range<filter_iterator<detail::IterOfRange<RangeT>, PredicateT>> |
333 | make_filter_range(RangeT &&Range, PredicateT Pred) { |
334 | using FilterIteratorT = |
335 | filter_iterator<detail::IterOfRange<RangeT>, PredicateT>; |
336 | return make_range(FilterIteratorT(std::begin(std::forward<RangeT>(Range)), |
337 | std::end(std::forward<RangeT>(Range)), |
338 | std::move(Pred)), |
339 | FilterIteratorT(std::end(std::forward<RangeT>(Range)))); |
340 | } |
341 | |
342 | // forward declarations required by zip_shortest/zip_first |
343 | template <typename R, typename UnaryPredicate> |
344 | bool all_of(R &&range, UnaryPredicate P); |
345 | |
346 | template <size_t... I> struct index_sequence; |
347 | |
348 | template <class... Ts> struct index_sequence_for; |
349 | |
350 | namespace detail { |
351 | |
352 | using std::declval; |
353 | |
354 | // We have to alias this since inlining the actual type at the usage site |
355 | // in the parameter list of iterator_facade_base<> below ICEs MSVC 2017. |
356 | template<typename... Iters> struct ZipTupleType { |
357 | using type = std::tuple<decltype(*declval<Iters>())...>; |
358 | }; |
359 | |
360 | template <typename ZipType, typename... Iters> |
361 | using zip_traits = iterator_facade_base< |
362 | ZipType, typename std::common_type<std::bidirectional_iterator_tag, |
363 | typename std::iterator_traits< |
364 | Iters>::iterator_category...>::type, |
365 | // ^ TODO: Implement random access methods. |
366 | typename ZipTupleType<Iters...>::type, |
367 | typename std::iterator_traits<typename std::tuple_element< |
368 | 0, std::tuple<Iters...>>::type>::difference_type, |
369 | // ^ FIXME: This follows boost::make_zip_iterator's assumption that all |
370 | // inner iterators have the same difference_type. It would fail if, for |
371 | // instance, the second field's difference_type were non-numeric while the |
372 | // first is. |
373 | typename ZipTupleType<Iters...>::type *, |
374 | typename ZipTupleType<Iters...>::type>; |
375 | |
376 | template <typename ZipType, typename... Iters> |
377 | struct zip_common : public zip_traits<ZipType, Iters...> { |
378 | using Base = zip_traits<ZipType, Iters...>; |
379 | using value_type = typename Base::value_type; |
380 | |
381 | std::tuple<Iters...> iterators; |
382 | |
383 | protected: |
384 | template <size_t... Ns> value_type deref(index_sequence<Ns...>) const { |
385 | return value_type(*std::get<Ns>(iterators)...); |
386 | } |
387 | |
388 | template <size_t... Ns> |
389 | decltype(iterators) tup_inc(index_sequence<Ns...>) const { |
390 | return std::tuple<Iters...>(std::next(std::get<Ns>(iterators))...); |
391 | } |
392 | |
393 | template <size_t... Ns> |
394 | decltype(iterators) tup_dec(index_sequence<Ns...>) const { |
395 | return std::tuple<Iters...>(std::prev(std::get<Ns>(iterators))...); |
396 | } |
397 | |
398 | public: |
399 | zip_common(Iters &&... ts) : iterators(std::forward<Iters>(ts)...) {} |
400 | |
401 | value_type operator*() { return deref(index_sequence_for<Iters...>{}); } |
402 | |
403 | const value_type operator*() const { |
404 | return deref(index_sequence_for<Iters...>{}); |
405 | } |
406 | |
407 | ZipType &operator++() { |
408 | iterators = tup_inc(index_sequence_for<Iters...>{}); |
409 | return *reinterpret_cast<ZipType *>(this); |
410 | } |
411 | |
412 | ZipType &operator--() { |
413 | static_assert(Base::IsBidirectional, |
414 | "All inner iterators must be at least bidirectional."); |
415 | iterators = tup_dec(index_sequence_for<Iters...>{}); |
416 | return *reinterpret_cast<ZipType *>(this); |
417 | } |
418 | }; |
419 | |
420 | template <typename... Iters> |
421 | struct zip_first : public zip_common<zip_first<Iters...>, Iters...> { |
422 | using Base = zip_common<zip_first<Iters...>, Iters...>; |
423 | |
424 | bool operator==(const zip_first<Iters...> &other) const { |
425 | return std::get<0>(this->iterators) == std::get<0>(other.iterators); |
426 | } |
427 | |
428 | zip_first(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {} |
429 | }; |
430 | |
431 | template <typename... Iters> |
432 | class zip_shortest : public zip_common<zip_shortest<Iters...>, Iters...> { |
433 | template <size_t... Ns> |
434 | bool test(const zip_shortest<Iters...> &other, index_sequence<Ns...>) const { |
435 | return all_of(std::initializer_list<bool>{std::get<Ns>(this->iterators) != |
436 | std::get<Ns>(other.iterators)...}, |
437 | identity<bool>{}); |
438 | } |
439 | |
440 | public: |
441 | using Base = zip_common<zip_shortest<Iters...>, Iters...>; |
442 | |
443 | zip_shortest(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {} |
444 | |
445 | bool operator==(const zip_shortest<Iters...> &other) const { |
446 | return !test(other, index_sequence_for<Iters...>{}); |
447 | } |
448 | }; |
449 | |
450 | template <template <typename...> class ItType, typename... Args> class zippy { |
451 | public: |
452 | using iterator = ItType<decltype(std::begin(std::declval<Args>()))...>; |
453 | using iterator_category = typename iterator::iterator_category; |
454 | using value_type = typename iterator::value_type; |
455 | using difference_type = typename iterator::difference_type; |
456 | using pointer = typename iterator::pointer; |
457 | using reference = typename iterator::reference; |
458 | |
459 | private: |
460 | std::tuple<Args...> ts; |
461 | |
462 | template <size_t... Ns> iterator begin_impl(index_sequence<Ns...>) const { |
463 | return iterator(std::begin(std::get<Ns>(ts))...); |
464 | } |
465 | template <size_t... Ns> iterator end_impl(index_sequence<Ns...>) const { |
466 | return iterator(std::end(std::get<Ns>(ts))...); |
467 | } |
468 | |
469 | public: |
470 | zippy(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {} |
471 | |
472 | iterator begin() const { return begin_impl(index_sequence_for<Args...>{}); } |
473 | iterator end() const { return end_impl(index_sequence_for<Args...>{}); } |
474 | }; |
475 | |
476 | } // end namespace detail |
477 | |
478 | /// zip iterator for two or more iteratable types. |
479 | template <typename T, typename U, typename... Args> |
480 | detail::zippy<detail::zip_shortest, T, U, Args...> zip(T &&t, U &&u, |
481 | Args &&... args) { |
482 | return detail::zippy<detail::zip_shortest, T, U, Args...>( |
483 | std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...); |
484 | } |
485 | |
486 | /// zip iterator that, for the sake of efficiency, assumes the first iteratee to |
487 | /// be the shortest. |
488 | template <typename T, typename U, typename... Args> |
489 | detail::zippy<detail::zip_first, T, U, Args...> zip_first(T &&t, U &&u, |
490 | Args &&... args) { |
491 | return detail::zippy<detail::zip_first, T, U, Args...>( |
492 | std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...); |
493 | } |
494 | |
495 | /// Iterator wrapper that concatenates sequences together. |
496 | /// |
497 | /// This can concatenate different iterators, even with different types, into |
498 | /// a single iterator provided the value types of all the concatenated |
499 | /// iterators expose `reference` and `pointer` types that can be converted to |
500 | /// `ValueT &` and `ValueT *` respectively. It doesn't support more |
501 | /// interesting/customized pointer or reference types. |
502 | /// |
503 | /// Currently this only supports forward or higher iterator categories as |
504 | /// inputs and always exposes a forward iterator interface. |
505 | template <typename ValueT, typename... IterTs> |
506 | class concat_iterator |
507 | : public iterator_facade_base<concat_iterator<ValueT, IterTs...>, |
508 | std::forward_iterator_tag, ValueT> { |
509 | using BaseT = typename concat_iterator::iterator_facade_base; |
510 | |
511 | /// We store both the current and end iterators for each concatenated |
512 | /// sequence in a tuple of pairs. |
513 | /// |
514 | /// Note that something like iterator_range seems nice at first here, but the |
515 | /// range properties are of little benefit and end up getting in the way |
516 | /// because we need to do mutation on the current iterators. |
517 | std::tuple<std::pair<IterTs, IterTs>...> IterPairs; |
518 | |
519 | /// Attempts to increment a specific iterator. |
520 | /// |
521 | /// Returns true if it was able to increment the iterator. Returns false if |
522 | /// the iterator is already at the end iterator. |
523 | template <size_t Index> bool incrementHelper() { |
524 | auto &IterPair = std::get<Index>(IterPairs); |
525 | if (IterPair.first == IterPair.second) |
526 | return false; |
527 | |
528 | ++IterPair.first; |
529 | return true; |
530 | } |
531 | |
532 | /// Increments the first non-end iterator. |
533 | /// |
534 | /// It is an error to call this with all iterators at the end. |
535 | template <size_t... Ns> void increment(index_sequence<Ns...>) { |
536 | // Build a sequence of functions to increment each iterator if possible. |
537 | bool (concat_iterator::*IncrementHelperFns[])() = { |
538 | &concat_iterator::incrementHelper<Ns>...}; |
539 | |
540 | // Loop over them, and stop as soon as we succeed at incrementing one. |
541 | for (auto &IncrementHelperFn : IncrementHelperFns) |
542 | if ((this->*IncrementHelperFn)()) |
543 | return; |
544 | |
545 | llvm_unreachable("Attempted to increment an end concat iterator!")::llvm::llvm_unreachable_internal("Attempted to increment an end concat iterator!" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/ADT/STLExtras.h" , 545); |
546 | } |
547 | |
548 | /// Returns null if the specified iterator is at the end. Otherwise, |
549 | /// dereferences the iterator and returns the address of the resulting |
550 | /// reference. |
551 | template <size_t Index> ValueT *getHelper() const { |
552 | auto &IterPair = std::get<Index>(IterPairs); |
553 | if (IterPair.first == IterPair.second) |
554 | return nullptr; |
555 | |
556 | return &*IterPair.first; |
557 | } |
558 | |
559 | /// Finds the first non-end iterator, dereferences, and returns the resulting |
560 | /// reference. |
561 | /// |
562 | /// It is an error to call this with all iterators at the end. |
563 | template <size_t... Ns> ValueT &get(index_sequence<Ns...>) const { |
564 | // Build a sequence of functions to get from iterator if possible. |
565 | ValueT *(concat_iterator::*GetHelperFns[])() const = { |
566 | &concat_iterator::getHelper<Ns>...}; |
567 | |
568 | // Loop over them, and return the first result we find. |
569 | for (auto &GetHelperFn : GetHelperFns) |
570 | if (ValueT *P = (this->*GetHelperFn)()) |
571 | return *P; |
572 | |
573 | llvm_unreachable("Attempted to get a pointer from an end concat iterator!")::llvm::llvm_unreachable_internal("Attempted to get a pointer from an end concat iterator!" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/ADT/STLExtras.h" , 573); |
574 | } |
575 | |
576 | public: |
577 | /// Constructs an iterator from a squence of ranges. |
578 | /// |
579 | /// We need the full range to know how to switch between each of the |
580 | /// iterators. |
581 | template <typename... RangeTs> |
582 | explicit concat_iterator(RangeTs &&... Ranges) |
583 | : IterPairs({std::begin(Ranges), std::end(Ranges)}...) {} |
584 | |
585 | using BaseT::operator++; |
586 | |
587 | concat_iterator &operator++() { |
588 | increment(index_sequence_for<IterTs...>()); |
589 | return *this; |
590 | } |
591 | |
592 | ValueT &operator*() const { return get(index_sequence_for<IterTs...>()); } |
593 | |
594 | bool operator==(const concat_iterator &RHS) const { |
595 | return IterPairs == RHS.IterPairs; |
596 | } |
597 | }; |
598 | |
599 | namespace detail { |
600 | |
601 | /// Helper to store a sequence of ranges being concatenated and access them. |
602 | /// |
603 | /// This is designed to facilitate providing actual storage when temporaries |
604 | /// are passed into the constructor such that we can use it as part of range |
605 | /// based for loops. |
606 | template <typename ValueT, typename... RangeTs> class concat_range { |
607 | public: |
608 | using iterator = |
609 | concat_iterator<ValueT, |
610 | decltype(std::begin(std::declval<RangeTs &>()))...>; |
611 | |
612 | private: |
613 | std::tuple<RangeTs...> Ranges; |
614 | |
615 | template <size_t... Ns> iterator begin_impl(index_sequence<Ns...>) { |
616 | return iterator(std::get<Ns>(Ranges)...); |
617 | } |
618 | template <size_t... Ns> iterator end_impl(index_sequence<Ns...>) { |
619 | return iterator(make_range(std::end(std::get<Ns>(Ranges)), |
620 | std::end(std::get<Ns>(Ranges)))...); |
621 | } |
622 | |
623 | public: |
624 | concat_range(RangeTs &&... Ranges) |
625 | : Ranges(std::forward<RangeTs>(Ranges)...) {} |
626 | |
627 | iterator begin() { return begin_impl(index_sequence_for<RangeTs...>{}); } |
628 | iterator end() { return end_impl(index_sequence_for<RangeTs...>{}); } |
629 | }; |
630 | |
631 | } // end namespace detail |
632 | |
633 | /// Concatenated range across two or more ranges. |
634 | /// |
635 | /// The desired value type must be explicitly specified. |
636 | template <typename ValueT, typename... RangeTs> |
637 | detail::concat_range<ValueT, RangeTs...> concat(RangeTs &&... Ranges) { |
638 | static_assert(sizeof...(RangeTs) > 1, |
639 | "Need more than one range to concatenate!"); |
640 | return detail::concat_range<ValueT, RangeTs...>( |
641 | std::forward<RangeTs>(Ranges)...); |
642 | } |
643 | |
644 | //===----------------------------------------------------------------------===// |
645 | // Extra additions to <utility> |
646 | //===----------------------------------------------------------------------===// |
647 | |
648 | /// \brief Function object to check whether the first component of a std::pair |
649 | /// compares less than the first component of another std::pair. |
650 | struct less_first { |
651 | template <typename T> bool operator()(const T &lhs, const T &rhs) const { |
652 | return lhs.first < rhs.first; |
653 | } |
654 | }; |
655 | |
656 | /// \brief Function object to check whether the second component of a std::pair |
657 | /// compares less than the second component of another std::pair. |
658 | struct less_second { |
659 | template <typename T> bool operator()(const T &lhs, const T &rhs) const { |
660 | return lhs.second < rhs.second; |
661 | } |
662 | }; |
663 | |
664 | // A subset of N3658. More stuff can be added as-needed. |
665 | |
666 | /// \brief Represents a compile-time sequence of integers. |
667 | template <class T, T... I> struct integer_sequence { |
668 | using value_type = T; |
669 | |
670 | static constexpr size_t size() { return sizeof...(I); } |
671 | }; |
672 | |
673 | /// \brief Alias for the common case of a sequence of size_ts. |
674 | template <size_t... I> |
675 | struct index_sequence : integer_sequence<std::size_t, I...> {}; |
676 | |
677 | template <std::size_t N, std::size_t... I> |
678 | struct build_index_impl : build_index_impl<N - 1, N - 1, I...> {}; |
679 | template <std::size_t... I> |
680 | struct build_index_impl<0, I...> : index_sequence<I...> {}; |
681 | |
682 | /// \brief Creates a compile-time integer sequence for a parameter pack. |
683 | template <class... Ts> |
684 | struct index_sequence_for : build_index_impl<sizeof...(Ts)> {}; |
685 | |
686 | /// Utility type to build an inheritance chain that makes it easy to rank |
687 | /// overload candidates. |
688 | template <int N> struct rank : rank<N - 1> {}; |
689 | template <> struct rank<0> {}; |
690 | |
691 | /// \brief traits class for checking whether type T is one of any of the given |
692 | /// types in the variadic list. |
693 | template <typename T, typename... Ts> struct is_one_of { |
694 | static const bool value = false; |
695 | }; |
696 | |
697 | template <typename T, typename U, typename... Ts> |
698 | struct is_one_of<T, U, Ts...> { |
699 | static const bool value = |
700 | std::is_same<T, U>::value || is_one_of<T, Ts...>::value; |
701 | }; |
702 | |
703 | /// \brief traits class for checking whether type T is a base class for all |
704 | /// the given types in the variadic list. |
705 | template <typename T, typename... Ts> struct are_base_of { |
706 | static const bool value = true; |
707 | }; |
708 | |
709 | template <typename T, typename U, typename... Ts> |
710 | struct are_base_of<T, U, Ts...> { |
711 | static const bool value = |
712 | std::is_base_of<T, U>::value && are_base_of<T, Ts...>::value; |
713 | }; |
714 | |
715 | //===----------------------------------------------------------------------===// |
716 | // Extra additions for arrays |
717 | //===----------------------------------------------------------------------===// |
718 | |
719 | /// Find the length of an array. |
720 | template <class T, std::size_t N> |
721 | constexpr inline size_t array_lengthof(T (&)[N]) { |
722 | return N; |
723 | } |
724 | |
725 | /// Adapt std::less<T> for array_pod_sort. |
726 | template<typename T> |
727 | inline int array_pod_sort_comparator(const void *P1, const void *P2) { |
728 | if (std::less<T>()(*reinterpret_cast<const T*>(P1), |
729 | *reinterpret_cast<const T*>(P2))) |
730 | return -1; |
731 | if (std::less<T>()(*reinterpret_cast<const T*>(P2), |
732 | *reinterpret_cast<const T*>(P1))) |
733 | return 1; |
734 | return 0; |
735 | } |
736 | |
737 | /// get_array_pod_sort_comparator - This is an internal helper function used to |
738 | /// get type deduction of T right. |
739 | template<typename T> |
740 | inline int (*get_array_pod_sort_comparator(const T &)) |
741 | (const void*, const void*) { |
742 | return array_pod_sort_comparator<T>; |
743 | } |
744 | |
745 | /// array_pod_sort - This sorts an array with the specified start and end |
746 | /// extent. This is just like std::sort, except that it calls qsort instead of |
747 | /// using an inlined template. qsort is slightly slower than std::sort, but |
748 | /// most sorts are not performance critical in LLVM and std::sort has to be |
749 | /// template instantiated for each type, leading to significant measured code |
750 | /// bloat. This function should generally be used instead of std::sort where |
751 | /// possible. |
752 | /// |
753 | /// This function assumes that you have simple POD-like types that can be |
754 | /// compared with std::less and can be moved with memcpy. If this isn't true, |
755 | /// you should use std::sort. |
756 | /// |
757 | /// NOTE: If qsort_r were portable, we could allow a custom comparator and |
758 | /// default to std::less. |
759 | template<class IteratorTy> |
760 | inline void array_pod_sort(IteratorTy Start, IteratorTy End) { |
761 | // Don't inefficiently call qsort with one element or trigger undefined |
762 | // behavior with an empty sequence. |
763 | auto NElts = End - Start; |
764 | if (NElts <= 1) return; |
765 | qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start)); |
766 | } |
767 | |
768 | template <class IteratorTy> |
769 | inline void array_pod_sort( |
770 | IteratorTy Start, IteratorTy End, |
771 | int (*Compare)( |
772 | const typename std::iterator_traits<IteratorTy>::value_type *, |
773 | const typename std::iterator_traits<IteratorTy>::value_type *)) { |
774 | // Don't inefficiently call qsort with one element or trigger undefined |
775 | // behavior with an empty sequence. |
776 | auto NElts = End - Start; |
777 | if (NElts <= 1) return; |
778 | qsort(&*Start, NElts, sizeof(*Start), |
779 | reinterpret_cast<int (*)(const void *, const void *)>(Compare)); |
780 | } |
781 | |
782 | //===----------------------------------------------------------------------===// |
783 | // Extra additions to <algorithm> |
784 | //===----------------------------------------------------------------------===// |
785 | |
786 | /// For a container of pointers, deletes the pointers and then clears the |
787 | /// container. |
788 | template<typename Container> |
789 | void DeleteContainerPointers(Container &C) { |
790 | for (auto V : C) |
791 | delete V; |
792 | C.clear(); |
793 | } |
794 | |
795 | /// In a container of pairs (usually a map) whose second element is a pointer, |
796 | /// deletes the second elements and then clears the container. |
797 | template<typename Container> |
798 | void DeleteContainerSeconds(Container &C) { |
799 | for (auto &V : C) |
800 | delete V.second; |
801 | C.clear(); |
802 | } |
803 | |
804 | /// Provide wrappers to std::for_each which take ranges instead of having to |
805 | /// pass begin/end explicitly. |
806 | template <typename R, typename UnaryPredicate> |
807 | UnaryPredicate for_each(R &&Range, UnaryPredicate P) { |
808 | return std::for_each(adl_begin(Range), adl_end(Range), P); |
809 | } |
810 | |
811 | /// Provide wrappers to std::all_of which take ranges instead of having to pass |
812 | /// begin/end explicitly. |
813 | template <typename R, typename UnaryPredicate> |
814 | bool all_of(R &&Range, UnaryPredicate P) { |
815 | return std::all_of(adl_begin(Range), adl_end(Range), P); |
816 | } |
817 | |
818 | /// Provide wrappers to std::any_of which take ranges instead of having to pass |
819 | /// begin/end explicitly. |
820 | template <typename R, typename UnaryPredicate> |
821 | bool any_of(R &&Range, UnaryPredicate P) { |
822 | return std::any_of(adl_begin(Range), adl_end(Range), P); |
823 | } |
824 | |
825 | /// Provide wrappers to std::none_of which take ranges instead of having to pass |
826 | /// begin/end explicitly. |
827 | template <typename R, typename UnaryPredicate> |
828 | bool none_of(R &&Range, UnaryPredicate P) { |
829 | return std::none_of(adl_begin(Range), adl_end(Range), P); |
830 | } |
831 | |
832 | /// Provide wrappers to std::find which take ranges instead of having to pass |
833 | /// begin/end explicitly. |
834 | template <typename R, typename T> |
835 | auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range)) { |
836 | return std::find(adl_begin(Range), adl_end(Range), Val); |
837 | } |
838 | |
839 | /// Provide wrappers to std::find_if which take ranges instead of having to pass |
840 | /// begin/end explicitly. |
841 | template <typename R, typename UnaryPredicate> |
842 | auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { |
843 | return std::find_if(adl_begin(Range), adl_end(Range), P); |
844 | } |
845 | |
846 | template <typename R, typename UnaryPredicate> |
847 | auto find_if_not(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { |
848 | return std::find_if_not(adl_begin(Range), adl_end(Range), P); |
849 | } |
850 | |
851 | /// Provide wrappers to std::remove_if which take ranges instead of having to |
852 | /// pass begin/end explicitly. |
853 | template <typename R, typename UnaryPredicate> |
854 | auto remove_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { |
855 | return std::remove_if(adl_begin(Range), adl_end(Range), P); |
856 | } |
857 | |
858 | /// Provide wrappers to std::copy_if which take ranges instead of having to |
859 | /// pass begin/end explicitly. |
860 | template <typename R, typename OutputIt, typename UnaryPredicate> |
861 | OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P) { |
862 | return std::copy_if(adl_begin(Range), adl_end(Range), Out, P); |
863 | } |
864 | |
865 | template <typename R, typename OutputIt> |
866 | OutputIt copy(R &&Range, OutputIt Out) { |
867 | return std::copy(adl_begin(Range), adl_end(Range), Out); |
868 | } |
869 | |
870 | /// Wrapper function around std::find to detect if an element exists |
871 | /// in a container. |
872 | template <typename R, typename E> |
873 | bool is_contained(R &&Range, const E &Element) { |
874 | return std::find(adl_begin(Range), adl_end(Range), Element) != adl_end(Range); |
875 | } |
876 | |
877 | /// Wrapper function around std::count to count the number of times an element |
878 | /// \p Element occurs in the given range \p Range. |
879 | template <typename R, typename E> |
880 | auto count(R &&Range, const E &Element) -> |
881 | typename std::iterator_traits<decltype(adl_begin(Range))>::difference_type { |
882 | return std::count(adl_begin(Range), adl_end(Range), Element); |
883 | } |
884 | |
885 | /// Wrapper function around std::count_if to count the number of times an |
886 | /// element satisfying a given predicate occurs in a range. |
887 | template <typename R, typename UnaryPredicate> |
888 | auto count_if(R &&Range, UnaryPredicate P) -> |
889 | typename std::iterator_traits<decltype(adl_begin(Range))>::difference_type { |
890 | return std::count_if(adl_begin(Range), adl_end(Range), P); |
891 | } |
892 | |
893 | /// Wrapper function around std::transform to apply a function to a range and |
894 | /// store the result elsewhere. |
895 | template <typename R, typename OutputIt, typename UnaryPredicate> |
896 | OutputIt transform(R &&Range, OutputIt d_first, UnaryPredicate P) { |
897 | return std::transform(adl_begin(Range), adl_end(Range), d_first, P); |
898 | } |
899 | |
900 | /// Provide wrappers to std::partition which take ranges instead of having to |
901 | /// pass begin/end explicitly. |
902 | template <typename R, typename UnaryPredicate> |
903 | auto partition(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { |
904 | return std::partition(adl_begin(Range), adl_end(Range), P); |
905 | } |
906 | |
907 | /// Provide wrappers to std::lower_bound which take ranges instead of having to |
908 | /// pass begin/end explicitly. |
909 | template <typename R, typename ForwardIt> |
910 | auto lower_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range)) { |
911 | return std::lower_bound(adl_begin(Range), adl_end(Range), I); |
912 | } |
913 | |
914 | /// \brief Given a range of type R, iterate the entire range and return a |
915 | /// SmallVector with elements of the vector. This is useful, for example, |
916 | /// when you want to iterate a range and then sort the results. |
917 | template <unsigned Size, typename R> |
918 | SmallVector<typename std::remove_const<detail::ValueOfRange<R>>::type, Size> |
919 | to_vector(R &&Range) { |
920 | return {adl_begin(Range), adl_end(Range)}; |
921 | } |
922 | |
923 | /// Provide a container algorithm similar to C++ Library Fundamentals v2's |
924 | /// `erase_if` which is equivalent to: |
925 | /// |
926 | /// C.erase(remove_if(C, pred), C.end()); |
927 | /// |
928 | /// This version works for any container with an erase method call accepting |
929 | /// two iterators. |
930 | template <typename Container, typename UnaryPredicate> |
931 | void erase_if(Container &C, UnaryPredicate P) { |
932 | C.erase(remove_if(C, P), C.end()); |
933 | } |
934 | |
935 | //===----------------------------------------------------------------------===// |
936 | // Extra additions to <memory> |
937 | //===----------------------------------------------------------------------===// |
938 | |
939 | // Implement make_unique according to N3656. |
940 | |
941 | /// \brief Constructs a `new T()` with the given args and returns a |
942 | /// `unique_ptr<T>` which owns the object. |
943 | /// |
944 | /// Example: |
945 | /// |
946 | /// auto p = make_unique<int>(); |
947 | /// auto p = make_unique<std::tuple<int, int>>(0, 1); |
948 | template <class T, class... Args> |
949 | typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type |
950 | make_unique(Args &&... args) { |
951 | return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); |
952 | } |
953 | |
954 | /// \brief Constructs a `new T[n]` with the given args and returns a |
955 | /// `unique_ptr<T[]>` which owns the object. |
956 | /// |
957 | /// \param n size of the new array. |
958 | /// |
959 | /// Example: |
960 | /// |
961 | /// auto p = make_unique<int[]>(2); // value-initializes the array with 0's. |
962 | template <class T> |
963 | typename std::enable_if<std::is_array<T>::value && std::extent<T>::value == 0, |
964 | std::unique_ptr<T>>::type |
965 | make_unique(size_t n) { |
966 | return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]()); |
967 | } |
968 | |
969 | /// This function isn't used and is only here to provide better compile errors. |
970 | template <class T, class... Args> |
971 | typename std::enable_if<std::extent<T>::value != 0>::type |
972 | make_unique(Args &&...) = delete; |
973 | |
974 | struct FreeDeleter { |
975 | void operator()(void* v) { |
976 | ::free(v); |
977 | } |
978 | }; |
979 | |
980 | template<typename First, typename Second> |
981 | struct pair_hash { |
982 | size_t operator()(const std::pair<First, Second> &P) const { |
983 | return std::hash<First>()(P.first) * 31 + std::hash<Second>()(P.second); |
984 | } |
985 | }; |
986 | |
987 | /// A functor like C++14's std::less<void> in its absence. |
988 | struct less { |
989 | template <typename A, typename B> bool operator()(A &&a, B &&b) const { |
990 | return std::forward<A>(a) < std::forward<B>(b); |
991 | } |
992 | }; |
993 | |
994 | /// A functor like C++14's std::equal<void> in its absence. |
995 | struct equal { |
996 | template <typename A, typename B> bool operator()(A &&a, B &&b) const { |
997 | return std::forward<A>(a) == std::forward<B>(b); |
998 | } |
999 | }; |
1000 | |
1001 | /// Binary functor that adapts to any other binary functor after dereferencing |
1002 | /// operands. |
1003 | template <typename T> struct deref { |
1004 | T func; |
1005 | |
1006 | // Could be further improved to cope with non-derivable functors and |
1007 | // non-binary functors (should be a variadic template member function |
1008 | // operator()). |
1009 | template <typename A, typename B> |
1010 | auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) { |
1011 | assert(lhs)(static_cast <bool> (lhs) ? void (0) : __assert_fail ("lhs" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/ADT/STLExtras.h" , 1011, __extension__ __PRETTY_FUNCTION__)); |
1012 | assert(rhs)(static_cast <bool> (rhs) ? void (0) : __assert_fail ("rhs" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/ADT/STLExtras.h" , 1012, __extension__ __PRETTY_FUNCTION__)); |
1013 | return func(*lhs, *rhs); |
1014 | } |
1015 | }; |
1016 | |
1017 | namespace detail { |
1018 | |
1019 | template <typename R> class enumerator_iter; |
1020 | |
1021 | template <typename R> struct result_pair { |
1022 | friend class enumerator_iter<R>; |
1023 | |
1024 | result_pair() = default; |
1025 | result_pair(std::size_t Index, IterOfRange<R> Iter) |
1026 | : Index(Index), Iter(Iter) {} |
1027 | |
1028 | result_pair<R> &operator=(const result_pair<R> &Other) { |
1029 | Index = Other.Index; |
1030 | Iter = Other.Iter; |
1031 | return *this; |
1032 | } |
1033 | |
1034 | std::size_t index() const { return Index; } |
1035 | const ValueOfRange<R> &value() const { return *Iter; } |
1036 | ValueOfRange<R> &value() { return *Iter; } |
1037 | |
1038 | private: |
1039 | std::size_t Index = std::numeric_limits<std::size_t>::max(); |
1040 | IterOfRange<R> Iter; |
1041 | }; |
1042 | |
1043 | template <typename R> |
1044 | class enumerator_iter |
1045 | : public iterator_facade_base< |
1046 | enumerator_iter<R>, std::forward_iterator_tag, result_pair<R>, |
1047 | typename std::iterator_traits<IterOfRange<R>>::difference_type, |
1048 | typename std::iterator_traits<IterOfRange<R>>::pointer, |
1049 | typename std::iterator_traits<IterOfRange<R>>::reference> { |
1050 | using result_type = result_pair<R>; |
1051 | |
1052 | public: |
1053 | explicit enumerator_iter(IterOfRange<R> EndIter) |
1054 | : Result(std::numeric_limits<size_t>::max(), EndIter) {} |
1055 | |
1056 | enumerator_iter(std::size_t Index, IterOfRange<R> Iter) |
1057 | : Result(Index, Iter) {} |
1058 | |
1059 | result_type &operator*() { return Result; } |
1060 | const result_type &operator*() const { return Result; } |
1061 | |
1062 | enumerator_iter<R> &operator++() { |
1063 | assert(Result.Index != std::numeric_limits<size_t>::max())(static_cast <bool> (Result.Index != std::numeric_limits <size_t>::max()) ? void (0) : __assert_fail ("Result.Index != std::numeric_limits<size_t>::max()" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/ADT/STLExtras.h" , 1063, __extension__ __PRETTY_FUNCTION__)); |
1064 | ++Result.Iter; |
1065 | ++Result.Index; |
1066 | return *this; |
1067 | } |
1068 | |
1069 | bool operator==(const enumerator_iter<R> &RHS) const { |
1070 | // Don't compare indices here, only iterators. It's possible for an end |
1071 | // iterator to have different indices depending on whether it was created |
1072 | // by calling std::end() versus incrementing a valid iterator. |
1073 | return Result.Iter == RHS.Result.Iter; |
1074 | } |
1075 | |
1076 | enumerator_iter<R> &operator=(const enumerator_iter<R> &Other) { |
1077 | Result = Other.Result; |
1078 | return *this; |
1079 | } |
1080 | |
1081 | private: |
1082 | result_type Result; |
1083 | }; |
1084 | |
1085 | template <typename R> class enumerator { |
1086 | public: |
1087 | explicit enumerator(R &&Range) : TheRange(std::forward<R>(Range)) {} |
1088 | |
1089 | enumerator_iter<R> begin() { |
1090 | return enumerator_iter<R>(0, std::begin(TheRange)); |
1091 | } |
1092 | |
1093 | enumerator_iter<R> end() { |
1094 | return enumerator_iter<R>(std::end(TheRange)); |
1095 | } |
1096 | |
1097 | private: |
1098 | R TheRange; |
1099 | }; |
1100 | |
1101 | } // end namespace detail |
1102 | |
1103 | /// Given an input range, returns a new range whose values are are pair (A,B) |
1104 | /// such that A is the 0-based index of the item in the sequence, and B is |
1105 | /// the value from the original sequence. Example: |
1106 | /// |
1107 | /// std::vector<char> Items = {'A', 'B', 'C', 'D'}; |
1108 | /// for (auto X : enumerate(Items)) { |
1109 | /// printf("Item %d - %c\n", X.index(), X.value()); |
1110 | /// } |
1111 | /// |
1112 | /// Output: |
1113 | /// Item 0 - A |
1114 | /// Item 1 - B |
1115 | /// Item 2 - C |
1116 | /// Item 3 - D |
1117 | /// |
1118 | template <typename R> detail::enumerator<R> enumerate(R &&TheRange) { |
1119 | return detail::enumerator<R>(std::forward<R>(TheRange)); |
1120 | } |
1121 | |
1122 | namespace detail { |
1123 | |
1124 | template <typename F, typename Tuple, std::size_t... I> |
1125 | auto apply_tuple_impl(F &&f, Tuple &&t, index_sequence<I...>) |
1126 | -> decltype(std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...)) { |
1127 | return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...); |
1128 | } |
1129 | |
1130 | } // end namespace detail |
1131 | |
1132 | /// Given an input tuple (a1, a2, ..., an), pass the arguments of the |
1133 | /// tuple variadically to f as if by calling f(a1, a2, ..., an) and |
1134 | /// return the result. |
1135 | template <typename F, typename Tuple> |
1136 | auto apply_tuple(F &&f, Tuple &&t) -> decltype(detail::apply_tuple_impl( |
1137 | std::forward<F>(f), std::forward<Tuple>(t), |
1138 | build_index_impl< |
1139 | std::tuple_size<typename std::decay<Tuple>::type>::value>{})) { |
1140 | using Indices = build_index_impl< |
1141 | std::tuple_size<typename std::decay<Tuple>::type>::value>; |
1142 | |
1143 | return detail::apply_tuple_impl(std::forward<F>(f), std::forward<Tuple>(t), |
1144 | Indices{}); |
1145 | } |
1146 | |
1147 | } // end namespace llvm |
1148 | |
1149 | #endif // LLVM_ADT_STLEXTRAS_H |
1 | //===- CoverageMapping.h - Code coverage mapping support --------*- C++ -*-===// |
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 | // Code coverage mapping data is generated by clang and read by |
11 | // llvm-cov to show code coverage statistics for a file. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #ifndef LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H |
16 | #define LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H |
17 | |
18 | #include "llvm/ADT/ArrayRef.h" |
19 | #include "llvm/ADT/DenseMap.h" |
20 | #include "llvm/ADT/Hashing.h" |
21 | #include "llvm/ADT/None.h" |
22 | #include "llvm/ADT/StringRef.h" |
23 | #include "llvm/ADT/StringSet.h" |
24 | #include "llvm/ADT/iterator.h" |
25 | #include "llvm/ADT/iterator_range.h" |
26 | #include "llvm/ProfileData/InstrProf.h" |
27 | #include "llvm/Support/Compiler.h" |
28 | #include "llvm/Support/Debug.h" |
29 | #include "llvm/Support/Endian.h" |
30 | #include "llvm/Support/Error.h" |
31 | #include "llvm/Support/raw_ostream.h" |
32 | #include <cassert> |
33 | #include <cstdint> |
34 | #include <iterator> |
35 | #include <memory> |
36 | #include <string> |
37 | #include <system_error> |
38 | #include <tuple> |
39 | #include <utility> |
40 | #include <vector> |
41 | |
42 | namespace llvm { |
43 | |
44 | class IndexedInstrProfReader; |
45 | |
46 | namespace coverage { |
47 | |
48 | class CoverageMappingReader; |
49 | struct CoverageMappingRecord; |
50 | |
51 | enum class coveragemap_error { |
52 | success = 0, |
53 | eof, |
54 | no_data_found, |
55 | unsupported_version, |
56 | truncated, |
57 | malformed |
58 | }; |
59 | |
60 | const std::error_category &coveragemap_category(); |
61 | |
62 | inline std::error_code make_error_code(coveragemap_error E) { |
63 | return std::error_code(static_cast<int>(E), coveragemap_category()); |
64 | } |
65 | |
66 | class CoverageMapError : public ErrorInfo<CoverageMapError> { |
67 | public: |
68 | CoverageMapError(coveragemap_error Err) : Err(Err) { |
69 | assert(Err != coveragemap_error::success && "Not an error")(static_cast <bool> (Err != coveragemap_error::success && "Not an error") ? void (0) : __assert_fail ("Err != coveragemap_error::success && \"Not an error\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/ProfileData/Coverage/CoverageMapping.h" , 69, __extension__ __PRETTY_FUNCTION__)); |
70 | } |
71 | |
72 | std::string message() const override; |
73 | |
74 | void log(raw_ostream &OS) const override { OS << message(); } |
75 | |
76 | std::error_code convertToErrorCode() const override { |
77 | return make_error_code(Err); |
78 | } |
79 | |
80 | coveragemap_error get() const { return Err; } |
81 | |
82 | static char ID; |
83 | |
84 | private: |
85 | coveragemap_error Err; |
86 | }; |
87 | |
88 | /// A Counter is an abstract value that describes how to compute the |
89 | /// execution count for a region of code using the collected profile count data. |
90 | struct Counter { |
91 | enum CounterKind { Zero, CounterValueReference, Expression }; |
92 | static const unsigned EncodingTagBits = 2; |
93 | static const unsigned EncodingTagMask = 0x3; |
94 | static const unsigned EncodingCounterTagAndExpansionRegionTagBits = |
95 | EncodingTagBits + 1; |
96 | |
97 | private: |
98 | CounterKind Kind = Zero; |
99 | unsigned ID = 0; |
100 | |
101 | Counter(CounterKind Kind, unsigned ID) : Kind(Kind), ID(ID) {} |
102 | |
103 | public: |
104 | Counter() = default; |
105 | |
106 | CounterKind getKind() const { return Kind; } |
107 | |
108 | bool isZero() const { return Kind == Zero; } |
109 | |
110 | bool isExpression() const { return Kind == Expression; } |
111 | |
112 | unsigned getCounterID() const { return ID; } |
113 | |
114 | unsigned getExpressionID() const { return ID; } |
115 | |
116 | friend bool operator==(const Counter &LHS, const Counter &RHS) { |
117 | return LHS.Kind == RHS.Kind && LHS.ID == RHS.ID; |
118 | } |
119 | |
120 | friend bool operator!=(const Counter &LHS, const Counter &RHS) { |
121 | return !(LHS == RHS); |
122 | } |
123 | |
124 | friend bool operator<(const Counter &LHS, const Counter &RHS) { |
125 | return std::tie(LHS.Kind, LHS.ID) < std::tie(RHS.Kind, RHS.ID); |
126 | } |
127 | |
128 | /// Return the counter that represents the number zero. |
129 | static Counter getZero() { return Counter(); } |
130 | |
131 | /// Return the counter that corresponds to a specific profile counter. |
132 | static Counter getCounter(unsigned CounterId) { |
133 | return Counter(CounterValueReference, CounterId); |
134 | } |
135 | |
136 | /// Return the counter that corresponds to a specific addition counter |
137 | /// expression. |
138 | static Counter getExpression(unsigned ExpressionId) { |
139 | return Counter(Expression, ExpressionId); |
140 | } |
141 | }; |
142 | |
143 | /// A Counter expression is a value that represents an arithmetic operation |
144 | /// with two counters. |
145 | struct CounterExpression { |
146 | enum ExprKind { Subtract, Add }; |
147 | ExprKind Kind; |
148 | Counter LHS, RHS; |
149 | |
150 | CounterExpression(ExprKind Kind, Counter LHS, Counter RHS) |
151 | : Kind(Kind), LHS(LHS), RHS(RHS) {} |
152 | }; |
153 | |
154 | /// A Counter expression builder is used to construct the counter expressions. |
155 | /// It avoids unnecessary duplication and simplifies algebraic expressions. |
156 | class CounterExpressionBuilder { |
157 | /// A list of all the counter expressions |
158 | std::vector<CounterExpression> Expressions; |
159 | |
160 | /// A lookup table for the index of a given expression. |
161 | DenseMap<CounterExpression, unsigned> ExpressionIndices; |
162 | |
163 | /// Return the counter which corresponds to the given expression. |
164 | /// |
165 | /// If the given expression is already stored in the builder, a counter |
166 | /// that references that expression is returned. Otherwise, the given |
167 | /// expression is added to the builder's collection of expressions. |
168 | Counter get(const CounterExpression &E); |
169 | |
170 | /// Represents a term in a counter expression tree. |
171 | struct Term { |
172 | unsigned CounterID; |
173 | int Factor; |
174 | |
175 | Term(unsigned CounterID, int Factor) |
176 | : CounterID(CounterID), Factor(Factor) {} |
177 | }; |
178 | |
179 | /// Gather the terms of the expression tree for processing. |
180 | /// |
181 | /// This collects each addition and subtraction referenced by the counter into |
182 | /// a sequence that can be sorted and combined to build a simplified counter |
183 | /// expression. |
184 | void extractTerms(Counter C, int Sign, SmallVectorImpl<Term> &Terms); |
185 | |
186 | /// Simplifies the given expression tree |
187 | /// by getting rid of algebraically redundant operations. |
188 | Counter simplify(Counter ExpressionTree); |
189 | |
190 | public: |
191 | ArrayRef<CounterExpression> getExpressions() const { return Expressions; } |
192 | |
193 | /// Return a counter that represents the expression that adds LHS and RHS. |
194 | Counter add(Counter LHS, Counter RHS); |
195 | |
196 | /// Return a counter that represents the expression that subtracts RHS from |
197 | /// LHS. |
198 | Counter subtract(Counter LHS, Counter RHS); |
199 | }; |
200 | |
201 | using LineColPair = std::pair<unsigned, unsigned>; |
202 | |
203 | /// A Counter mapping region associates a source range with a specific counter. |
204 | struct CounterMappingRegion { |
205 | enum RegionKind { |
206 | /// A CodeRegion associates some code with a counter |
207 | CodeRegion, |
208 | |
209 | /// An ExpansionRegion represents a file expansion region that associates |
210 | /// a source range with the expansion of a virtual source file, such as |
211 | /// for a macro instantiation or #include file. |
212 | ExpansionRegion, |
213 | |
214 | /// A SkippedRegion represents a source range with code that was skipped |
215 | /// by a preprocessor or similar means. |
216 | SkippedRegion, |
217 | |
218 | /// A GapRegion is like a CodeRegion, but its count is only set as the |
219 | /// line execution count when its the only region in the line. |
220 | GapRegion |
221 | }; |
222 | |
223 | Counter Count; |
224 | unsigned FileID, ExpandedFileID; |
225 | unsigned LineStart, ColumnStart, LineEnd, ColumnEnd; |
226 | RegionKind Kind; |
227 | |
228 | CounterMappingRegion(Counter Count, unsigned FileID, unsigned ExpandedFileID, |
229 | unsigned LineStart, unsigned ColumnStart, |
230 | unsigned LineEnd, unsigned ColumnEnd, RegionKind Kind) |
231 | : Count(Count), FileID(FileID), ExpandedFileID(ExpandedFileID), |
232 | LineStart(LineStart), ColumnStart(ColumnStart), LineEnd(LineEnd), |
233 | ColumnEnd(ColumnEnd), Kind(Kind) {} |
234 | |
235 | static CounterMappingRegion |
236 | makeRegion(Counter Count, unsigned FileID, unsigned LineStart, |
237 | unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { |
238 | return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart, |
239 | LineEnd, ColumnEnd, CodeRegion); |
240 | } |
241 | |
242 | static CounterMappingRegion |
243 | makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart, |
244 | unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { |
245 | return CounterMappingRegion(Counter(), FileID, ExpandedFileID, LineStart, |
246 | ColumnStart, LineEnd, ColumnEnd, |
247 | ExpansionRegion); |
248 | } |
249 | |
250 | static CounterMappingRegion |
251 | makeSkipped(unsigned FileID, unsigned LineStart, unsigned ColumnStart, |
252 | unsigned LineEnd, unsigned ColumnEnd) { |
253 | return CounterMappingRegion(Counter(), FileID, 0, LineStart, ColumnStart, |
254 | LineEnd, ColumnEnd, SkippedRegion); |
255 | } |
256 | |
257 | static CounterMappingRegion |
258 | makeGapRegion(Counter Count, unsigned FileID, unsigned LineStart, |
259 | unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { |
260 | return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart, |
261 | LineEnd, (1U << 31) | ColumnEnd, GapRegion); |
262 | } |
263 | |
264 | inline LineColPair startLoc() const { |
265 | return LineColPair(LineStart, ColumnStart); |
266 | } |
267 | |
268 | inline LineColPair endLoc() const { return LineColPair(LineEnd, ColumnEnd); } |
269 | }; |
270 | |
271 | /// Associates a source range with an execution count. |
272 | struct CountedRegion : public CounterMappingRegion { |
273 | uint64_t ExecutionCount; |
274 | |
275 | CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount) |
276 | : CounterMappingRegion(R), ExecutionCount(ExecutionCount) {} |
277 | }; |
278 | |
279 | /// A Counter mapping context is used to connect the counters, expressions |
280 | /// and the obtained counter values. |
281 | class CounterMappingContext { |
282 | ArrayRef<CounterExpression> Expressions; |
283 | ArrayRef<uint64_t> CounterValues; |
284 | |
285 | public: |
286 | CounterMappingContext(ArrayRef<CounterExpression> Expressions, |
287 | ArrayRef<uint64_t> CounterValues = None) |
288 | : Expressions(Expressions), CounterValues(CounterValues) {} |
289 | |
290 | void setCounts(ArrayRef<uint64_t> Counts) { CounterValues = Counts; } |
291 | |
292 | void dump(const Counter &C, raw_ostream &OS) const; |
293 | void dump(const Counter &C) const { dump(C, dbgs()); } |
294 | |
295 | /// Return the number of times that a region of code associated with this |
296 | /// counter was executed. |
297 | Expected<int64_t> evaluate(const Counter &C) const; |
298 | }; |
299 | |
300 | /// Code coverage information for a single function. |
301 | struct FunctionRecord { |
302 | /// Raw function name. |
303 | std::string Name; |
304 | /// Associated files. |
305 | std::vector<std::string> Filenames; |
306 | /// Regions in the function along with their counts. |
307 | std::vector<CountedRegion> CountedRegions; |
308 | /// The number of times this function was executed. |
309 | uint64_t ExecutionCount; |
310 | |
311 | FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames) |
312 | : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {} |
313 | |
314 | FunctionRecord(FunctionRecord &&FR) = default; |
315 | FunctionRecord &operator=(FunctionRecord &&) = default; |
316 | |
317 | void pushRegion(CounterMappingRegion Region, uint64_t Count) { |
318 | if (CountedRegions.empty()) |
319 | ExecutionCount = Count; |
320 | CountedRegions.emplace_back(Region, Count); |
321 | } |
322 | }; |
323 | |
324 | /// Iterator over Functions, optionally filtered to a single file. |
325 | class FunctionRecordIterator |
326 | : public iterator_facade_base<FunctionRecordIterator, |
327 | std::forward_iterator_tag, FunctionRecord> { |
328 | ArrayRef<FunctionRecord> Records; |
329 | ArrayRef<FunctionRecord>::iterator Current; |
330 | StringRef Filename; |
331 | |
332 | /// Skip records whose primary file is not \c Filename. |
333 | void skipOtherFiles(); |
334 | |
335 | public: |
336 | FunctionRecordIterator(ArrayRef<FunctionRecord> Records_, |
337 | StringRef Filename = "") |
338 | : Records(Records_), Current(Records.begin()), Filename(Filename) { |
339 | skipOtherFiles(); |
340 | } |
341 | |
342 | FunctionRecordIterator() : Current(Records.begin()) {} |
343 | |
344 | bool operator==(const FunctionRecordIterator &RHS) const { |
345 | return Current == RHS.Current && Filename == RHS.Filename; |
346 | } |
347 | |
348 | const FunctionRecord &operator*() const { return *Current; } |
349 | |
350 | FunctionRecordIterator &operator++() { |
351 | assert(Current != Records.end() && "incremented past end")(static_cast <bool> (Current != Records.end() && "incremented past end") ? void (0) : __assert_fail ("Current != Records.end() && \"incremented past end\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/ProfileData/Coverage/CoverageMapping.h" , 351, __extension__ __PRETTY_FUNCTION__)); |
352 | ++Current; |
353 | skipOtherFiles(); |
354 | return *this; |
355 | } |
356 | }; |
357 | |
358 | /// Coverage information for a macro expansion or #included file. |
359 | /// |
360 | /// When covered code has pieces that can be expanded for more detail, such as a |
361 | /// preprocessor macro use and its definition, these are represented as |
362 | /// expansions whose coverage can be looked up independently. |
363 | struct ExpansionRecord { |
364 | /// The abstract file this expansion covers. |
365 | unsigned FileID; |
366 | /// The region that expands to this record. |
367 | const CountedRegion &Region; |
368 | /// Coverage for the expansion. |
369 | const FunctionRecord &Function; |
370 | |
371 | ExpansionRecord(const CountedRegion &Region, |
372 | const FunctionRecord &Function) |
373 | : FileID(Region.ExpandedFileID), Region(Region), Function(Function) {} |
374 | }; |
375 | |
376 | /// The execution count information starting at a point in a file. |
377 | /// |
378 | /// A sequence of CoverageSegments gives execution counts for a file in format |
379 | /// that's simple to iterate through for processing. |
380 | struct CoverageSegment { |
381 | /// The line where this segment begins. |
382 | unsigned Line; |
383 | /// The column where this segment begins. |
384 | unsigned Col; |
385 | /// The execution count, or zero if no count was recorded. |
386 | uint64_t Count; |
387 | /// When false, the segment was uninstrumented or skipped. |
388 | bool HasCount; |
389 | /// Whether this enters a new region or returns to a previous count. |
390 | bool IsRegionEntry; |
391 | /// Whether this enters a gap region. |
392 | bool IsGapRegion; |
393 | |
394 | CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry) |
395 | : Line(Line), Col(Col), Count(0), HasCount(false), |
396 | IsRegionEntry(IsRegionEntry), IsGapRegion(false) {} |
397 | |
398 | CoverageSegment(unsigned Line, unsigned Col, uint64_t Count, |
399 | bool IsRegionEntry, bool IsGapRegion = false) |
400 | : Line(Line), Col(Col), Count(Count), HasCount(true), |
401 | IsRegionEntry(IsRegionEntry), IsGapRegion(IsGapRegion) {} |
402 | |
403 | friend bool operator==(const CoverageSegment &L, const CoverageSegment &R) { |
404 | return std::tie(L.Line, L.Col, L.Count, L.HasCount, L.IsRegionEntry, |
405 | L.IsGapRegion) == std::tie(R.Line, R.Col, R.Count, |
406 | R.HasCount, R.IsRegionEntry, |
407 | R.IsGapRegion); |
408 | } |
409 | }; |
410 | |
411 | /// An instantiation group contains a \c FunctionRecord list, such that each |
412 | /// record corresponds to a distinct instantiation of the same function. |
413 | /// |
414 | /// Note that it's possible for a function to have more than one instantiation |
415 | /// (consider C++ template specializations or static inline functions). |
416 | class InstantiationGroup { |
417 | friend class CoverageMapping; |
418 | |
419 | unsigned Line; |
420 | unsigned Col; |
421 | std::vector<const FunctionRecord *> Instantiations; |
422 | |
423 | InstantiationGroup(unsigned Line, unsigned Col, |
424 | std::vector<const FunctionRecord *> Instantiations) |
425 | : Line(Line), Col(Col), Instantiations(std::move(Instantiations)) {} |
426 | |
427 | public: |
428 | InstantiationGroup(const InstantiationGroup &) = delete; |
429 | InstantiationGroup(InstantiationGroup &&) = default; |
430 | |
431 | /// Get the number of instantiations in this group. |
432 | size_t size() const { return Instantiations.size(); } |
433 | |
434 | /// Get the line where the common function was defined. |
435 | unsigned getLine() const { return Line; } |
436 | |
437 | /// Get the column where the common function was defined. |
438 | unsigned getColumn() const { return Col; } |
439 | |
440 | /// Check if the instantiations in this group have a common mangled name. |
441 | bool hasName() const { |
442 | for (unsigned I = 1, E = Instantiations.size(); I < E; ++I) |
443 | if (Instantiations[I]->Name != Instantiations[0]->Name) |
444 | return false; |
445 | return true; |
446 | } |
447 | |
448 | /// Get the common mangled name for instantiations in this group. |
449 | StringRef getName() const { |
450 | assert(hasName() && "Instantiations don't have a shared name")(static_cast <bool> (hasName() && "Instantiations don't have a shared name" ) ? void (0) : __assert_fail ("hasName() && \"Instantiations don't have a shared name\"" , "/build/llvm-toolchain-snapshot-7~svn326246/include/llvm/ProfileData/Coverage/CoverageMapping.h" , 450, __extension__ __PRETTY_FUNCTION__)); |
451 | return Instantiations[0]->Name; |
452 | } |
453 | |
454 | /// Get the total execution count of all instantiations in this group. |
455 | uint64_t getTotalExecutionCount() const { |
456 | uint64_t Count = 0; |
457 | for (const FunctionRecord *F : Instantiations) |
458 | Count += F->ExecutionCount; |
459 | return Count; |
460 | } |
461 | |
462 | /// Get the instantiations in this group. |
463 | ArrayRef<const FunctionRecord *> getInstantiations() const { |
464 | return Instantiations; |
465 | } |
466 | }; |
467 | |
468 | /// Coverage information to be processed or displayed. |
469 | /// |
470 | /// This represents the coverage of an entire file, expansion, or function. It |
471 | /// provides a sequence of CoverageSegments to iterate through, as well as the |
472 | /// list of expansions that can be further processed. |
473 | class CoverageData { |
474 | friend class CoverageMapping; |
475 | |
476 | std::string Filename; |
477 | std::vector<CoverageSegment> Segments; |
478 | std::vector<ExpansionRecord> Expansions; |
479 | |
480 | public: |
481 | CoverageData() = default; |
482 | |
483 | CoverageData(StringRef Filename) : Filename(Filename) {} |
484 | |
485 | /// Get the name of the file this data covers. |
486 | StringRef getFilename() const { return Filename; } |
487 | |
488 | /// Get an iterator over the coverage segments for this object. The segments |
489 | /// are guaranteed to be uniqued and sorted by location. |
490 | std::vector<CoverageSegment>::const_iterator begin() const { |
491 | return Segments.begin(); |
492 | } |
493 | |
494 | std::vector<CoverageSegment>::const_iterator end() const { |
495 | return Segments.end(); |
496 | } |
497 | |
498 | bool empty() const { return Segments.empty(); } |
499 | |
500 | /// Expansions that can be further processed. |
501 | ArrayRef<ExpansionRecord> getExpansions() const { return Expansions; } |
502 | }; |
503 | |
504 | /// The mapping of profile information to coverage data. |
505 | /// |
506 | /// This is the main interface to get coverage information, using a profile to |
507 | /// fill out execution counts. |
508 | class CoverageMapping { |
509 | StringSet<> FunctionNames; |
510 | std::vector<FunctionRecord> Functions; |
511 | std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches; |
512 | std::vector<std::pair<std::string, uint64_t>> FuncCounterMismatches; |
513 | |
514 | CoverageMapping() = default; |
515 | |
516 | /// Add a function record corresponding to \p Record. |
517 | Error loadFunctionRecord(const CoverageMappingRecord &Record, |
518 | IndexedInstrProfReader &ProfileReader); |
519 | |
520 | public: |
521 | CoverageMapping(const CoverageMapping &) = delete; |
522 | CoverageMapping &operator=(const CoverageMapping &) = delete; |
523 | |
524 | /// Load the coverage mapping using the given readers. |
525 | static Expected<std::unique_ptr<CoverageMapping>> |
526 | load(ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders, |
527 | IndexedInstrProfReader &ProfileReader); |
528 | |
529 | /// Load the coverage mapping from the given object files and profile. If |
530 | /// \p Arches is non-empty, it must specify an architecture for each object. |
531 | static Expected<std::unique_ptr<CoverageMapping>> |
532 | load(ArrayRef<StringRef> ObjectFilenames, StringRef ProfileFilename, |
533 | ArrayRef<StringRef> Arches = None); |
534 | |
535 | /// The number of functions that couldn't have their profiles mapped. |
536 | /// |
537 | /// This is a count of functions whose profile is out of date or otherwise |
538 | /// can't be associated with any coverage information. |
539 | unsigned getMismatchedCount() const { |
540 | return FuncHashMismatches.size() + FuncCounterMismatches.size(); |
541 | } |
542 | |
543 | /// A hash mismatch occurs when a profile record for a symbol does not have |
544 | /// the same hash as a coverage mapping record for the same symbol. This |
545 | /// returns a list of hash mismatches, where each mismatch is a pair of the |
546 | /// symbol name and its coverage mapping hash. |
547 | ArrayRef<std::pair<std::string, uint64_t>> getHashMismatches() const { |
548 | return FuncHashMismatches; |
549 | } |
550 | |
551 | /// A counter mismatch occurs when there is an error when evaluating the |
552 | /// counter expressions in a coverage mapping record. This returns a list of |
553 | /// counter mismatches, where each mismatch is a pair of the symbol name and |
554 | /// the number of valid evaluated counter expressions. |
555 | ArrayRef<std::pair<std::string, uint64_t>> getCounterMismatches() const { |
556 | return FuncCounterMismatches; |
557 | } |
558 | |
559 | /// Returns a lexicographically sorted, unique list of files that are |
560 | /// covered. |
561 | std::vector<StringRef> getUniqueSourceFiles() const; |
562 | |
563 | /// Get the coverage for a particular file. |
564 | /// |
565 | /// The given filename must be the name as recorded in the coverage |
566 | /// information. That is, only names returned from getUniqueSourceFiles will |
567 | /// yield a result. |
568 | CoverageData getCoverageForFile(StringRef Filename) const; |
569 | |
570 | /// Get the coverage for a particular function. |
571 | CoverageData getCoverageForFunction(const FunctionRecord &Function) const; |
572 | |
573 | /// Get the coverage for an expansion within a coverage set. |
574 | CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion) const; |
575 | |
576 | /// Gets all of the functions covered by this profile. |
577 | iterator_range<FunctionRecordIterator> getCoveredFunctions() const { |
578 | return make_range(FunctionRecordIterator(Functions), |
579 | FunctionRecordIterator()); |
580 | } |
581 | |
582 | /// Gets all of the functions in a particular file. |
583 | iterator_range<FunctionRecordIterator> |
584 | getCoveredFunctions(StringRef Filename) const { |
585 | return make_range(FunctionRecordIterator(Functions, Filename), |
586 | FunctionRecordIterator()); |
587 | } |
588 | |
589 | /// Get the list of function instantiation groups in a particular file. |
590 | /// |
591 | /// Every instantiation group in a program is attributed to exactly one file: |
592 | /// the file in which the definition for the common function begins. |
593 | std::vector<InstantiationGroup> |
594 | getInstantiationGroups(StringRef Filename) const; |
595 | }; |
596 | |
597 | /// Coverage statistics for a single line. |
598 | class LineCoverageStats { |
599 | uint64_t ExecutionCount; |
600 | bool HasMultipleRegions; |
601 | bool Mapped; |
602 | unsigned Line; |
603 | ArrayRef<const CoverageSegment *> LineSegments; |
604 | const CoverageSegment *WrappedSegment; |
605 | |
606 | friend class LineCoverageIterator; |
607 | LineCoverageStats() = default; |
608 | |
609 | public: |
610 | LineCoverageStats(ArrayRef<const CoverageSegment *> LineSegments, |
611 | const CoverageSegment *WrappedSegment, unsigned Line); |
612 | |
613 | uint64_t getExecutionCount() const { return ExecutionCount; } |
614 | |
615 | bool hasMultipleRegions() const { return HasMultipleRegions; } |
616 | |
617 | bool isMapped() const { return Mapped; } |
618 | |
619 | unsigned getLine() const { return Line; } |
620 | |
621 | ArrayRef<const CoverageSegment *> getLineSegments() const { |
622 | return LineSegments; |
623 | } |
624 | |
625 | const CoverageSegment *getWrappedSegment() const { return WrappedSegment; } |
626 | }; |
627 | |
628 | /// An iterator over the \c LineCoverageStats objects for lines described by |
629 | /// a \c CoverageData instance. |
630 | class LineCoverageIterator |
631 | : public iterator_facade_base< |
632 | LineCoverageIterator, std::forward_iterator_tag, LineCoverageStats> { |
633 | public: |
634 | LineCoverageIterator(const CoverageData &CD) |
635 | : LineCoverageIterator(CD, CD.begin()->Line) {} |
636 | |
637 | LineCoverageIterator(const CoverageData &CD, unsigned Line) |
638 | : CD(CD), WrappedSegment(nullptr), Next(CD.begin()), Ended(false), |
639 | Line(Line), Segments(), Stats() { |
640 | this->operator++(); |
641 | } |
642 | |
643 | LineCoverageIterator &operator=(const LineCoverageIterator &R) = default; |
644 | |
645 | bool operator==(const LineCoverageIterator &R) const { |
646 | return &CD == &R.CD && Next == R.Next && Ended == R.Ended; |
647 | } |
648 | |
649 | const LineCoverageStats &operator*() const { return Stats; } |
650 | |
651 | LineCoverageStats &operator*() { return Stats; } |
652 | |
653 | LineCoverageIterator &operator++(); |
654 | |
655 | LineCoverageIterator getEnd() const { |
656 | auto EndIt = *this; |
657 | EndIt.Next = CD.end(); |
658 | EndIt.Ended = true; |
659 | return EndIt; |
660 | } |
661 | |
662 | private: |
663 | const CoverageData &CD; |
664 | const CoverageSegment *WrappedSegment; |
665 | std::vector<CoverageSegment>::const_iterator Next; |
666 | bool Ended; |
667 | unsigned Line; |
668 | SmallVector<const CoverageSegment *, 4> Segments; |
669 | LineCoverageStats Stats; |
670 | }; |
671 | |
672 | /// Get a \c LineCoverageIterator range for the lines described by \p CD. |
673 | static inline iterator_range<LineCoverageIterator> |
674 | getLineCoverageStats(const coverage::CoverageData &CD) { |
675 | auto Begin = LineCoverageIterator(CD); |
676 | auto End = Begin.getEnd(); |
677 | return make_range(Begin, End); |
678 | } |
679 | |
680 | // Profile coverage map has the following layout: |
681 | // [CoverageMapFileHeader] |
682 | // [ArrayStart] |
683 | // [CovMapFunctionRecord] |
684 | // [CovMapFunctionRecord] |
685 | // ... |
686 | // [ArrayEnd] |
687 | // [Encoded Region Mapping Data] |
688 | LLVM_PACKED_STARTpack(push, 1) |
689 | template <class IntPtrT> struct CovMapFunctionRecordV1 { |
690 | #define COVMAP_V1 |
691 | #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name; |
692 | #include "llvm/ProfileData/InstrProfData.inc" |
693 | #undef COVMAP_V1 |
694 | |
695 | // Return the structural hash associated with the function. |
696 | template <support::endianness Endian> uint64_t getFuncHash() const { |
697 | return support::endian::byte_swap<uint64_t, Endian>(FuncHash); |
698 | } |
699 | |
700 | // Return the coverage map data size for the funciton. |
701 | template <support::endianness Endian> uint32_t getDataSize() const { |
702 | return support::endian::byte_swap<uint32_t, Endian>(DataSize); |
703 | } |
704 | |
705 | // Return function lookup key. The value is consider opaque. |
706 | template <support::endianness Endian> IntPtrT getFuncNameRef() const { |
707 | return support::endian::byte_swap<IntPtrT, Endian>(NamePtr); |
708 | } |
709 | |
710 | // Return the PGO name of the function */ |
711 | template <support::endianness Endian> |
712 | Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const { |
713 | IntPtrT NameRef = getFuncNameRef<Endian>(); |
714 | uint32_t NameS = support::endian::byte_swap<uint32_t, Endian>(NameSize); |
715 | FuncName = ProfileNames.getFuncName(NameRef, NameS); |
716 | if (NameS && FuncName.empty()) |
717 | return make_error<CoverageMapError>(coveragemap_error::malformed); |
718 | return Error::success(); |
719 | } |
720 | }; |
721 | |
722 | struct CovMapFunctionRecord { |
723 | #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name; |
724 | #include "llvm/ProfileData/InstrProfData.inc" |
725 | |
726 | // Return the structural hash associated with the function. |
727 | template <support::endianness Endian> uint64_t getFuncHash() const { |
728 | return support::endian::byte_swap<uint64_t, Endian>(FuncHash); |
729 | } |
730 | |
731 | // Return the coverage map data size for the funciton. |
732 | template <support::endianness Endian> uint32_t getDataSize() const { |
733 | return support::endian::byte_swap<uint32_t, Endian>(DataSize); |
734 | } |
735 | |
736 | // Return function lookup key. The value is consider opaque. |
737 | template <support::endianness Endian> uint64_t getFuncNameRef() const { |
738 | return support::endian::byte_swap<uint64_t, Endian>(NameRef); |
739 | } |
740 | |
741 | // Return the PGO name of the function */ |
742 | template <support::endianness Endian> |
743 | Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const { |
744 | uint64_t NameRef = getFuncNameRef<Endian>(); |
745 | FuncName = ProfileNames.getFuncName(NameRef); |
746 | return Error::success(); |
747 | } |
748 | }; |
749 | |
750 | // Per module coverage mapping data header, i.e. CoverageMapFileHeader |
751 | // documented above. |
752 | struct CovMapHeader { |
753 | #define COVMAP_HEADER(Type, LLVMType, Name, Init) Type Name; |
754 | #include "llvm/ProfileData/InstrProfData.inc" |
755 | template <support::endianness Endian> uint32_t getNRecords() const { |
756 | return support::endian::byte_swap<uint32_t, Endian>(NRecords); |
757 | } |
758 | |
759 | template <support::endianness Endian> uint32_t getFilenamesSize() const { |
760 | return support::endian::byte_swap<uint32_t, Endian>(FilenamesSize); |
761 | } |
762 | |
763 | template <support::endianness Endian> uint32_t getCoverageSize() const { |
764 | return support::endian::byte_swap<uint32_t, Endian>(CoverageSize); |
765 | } |
766 | |
767 | template <support::endianness Endian> uint32_t getVersion() const { |
768 | return support::endian::byte_swap<uint32_t, Endian>(Version); |
769 | } |
770 | }; |
771 | |
772 | LLVM_PACKED_ENDpack(pop) |
773 | |
774 | enum CovMapVersion { |
775 | Version1 = 0, |
776 | // Function's name reference from CovMapFuncRecord is changed from raw |
777 | // name string pointer to MD5 to support name section compression. Name |
778 | // section is also compressed. |
779 | Version2 = 1, |
780 | // A new interpretation of the columnEnd field is added in order to mark |
781 | // regions as gap areas. |
782 | Version3 = 2, |
783 | // The current version is Version3 |
784 | CurrentVersion = INSTR_PROF_COVMAP_VERSION2 |
785 | }; |
786 | |
787 | template <int CovMapVersion, class IntPtrT> struct CovMapTraits { |
788 | using CovMapFuncRecordType = CovMapFunctionRecord; |
789 | using NameRefType = uint64_t; |
790 | }; |
791 | |
792 | template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version1, IntPtrT> { |
793 | using CovMapFuncRecordType = CovMapFunctionRecordV1<IntPtrT>; |
794 | using NameRefType = IntPtrT; |
795 | }; |
796 | |
797 | } // end namespace coverage |
798 | |
799 | /// Provide DenseMapInfo for CounterExpression |
800 | template<> struct DenseMapInfo<coverage::CounterExpression> { |
801 | static inline coverage::CounterExpression getEmptyKey() { |
802 | using namespace coverage; |
803 | |
804 | return CounterExpression(CounterExpression::ExprKind::Subtract, |
805 | Counter::getCounter(~0U), |
806 | Counter::getCounter(~0U)); |
807 | } |
808 | |
809 | static inline coverage::CounterExpression getTombstoneKey() { |
810 | using namespace coverage; |
811 | |
812 | return CounterExpression(CounterExpression::ExprKind::Add, |
813 | Counter::getCounter(~0U), |
814 | Counter::getCounter(~0U)); |
815 | } |
816 | |
817 | static unsigned getHashValue(const coverage::CounterExpression &V) { |
818 | return static_cast<unsigned>( |
819 | hash_combine(V.Kind, V.LHS.getKind(), V.LHS.getCounterID(), |
820 | V.RHS.getKind(), V.RHS.getCounterID())); |
821 | } |
822 | |
823 | static bool isEqual(const coverage::CounterExpression &LHS, |
824 | const coverage::CounterExpression &RHS) { |
825 | return LHS.Kind == RHS.Kind && LHS.LHS == RHS.LHS && LHS.RHS == RHS.RHS; |
826 | } |
827 | }; |
828 | |
829 | } // end namespace llvm |
830 | |
831 | #endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H |