File: | build/source/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp |
Warning: | line 162, column 29 Moved-from object 'Err' is moved |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- tools/dsymutil/DwarfLinkerForBinary.cpp ----------------------------===// | |||
2 | // | |||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |||
4 | // See https://llvm.org/LICENSE.txt for license information. | |||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |||
6 | // | |||
7 | //===----------------------------------------------------------------------===// | |||
8 | ||||
9 | #include "DwarfLinkerForBinary.h" | |||
10 | #include "BinaryHolder.h" | |||
11 | #include "DebugMap.h" | |||
12 | #include "MachOUtils.h" | |||
13 | #include "dsymutil.h" | |||
14 | #include "llvm/ADT/ArrayRef.h" | |||
15 | #include "llvm/ADT/BitVector.h" | |||
16 | #include "llvm/ADT/DenseMap.h" | |||
17 | #include "llvm/ADT/DenseMapInfo.h" | |||
18 | #include "llvm/ADT/DenseSet.h" | |||
19 | #include "llvm/ADT/FoldingSet.h" | |||
20 | #include "llvm/ADT/Hashing.h" | |||
21 | #include "llvm/ADT/PointerIntPair.h" | |||
22 | #include "llvm/ADT/STLExtras.h" | |||
23 | #include "llvm/ADT/SmallString.h" | |||
24 | #include "llvm/ADT/StringMap.h" | |||
25 | #include "llvm/ADT/StringRef.h" | |||
26 | #include "llvm/ADT/Twine.h" | |||
27 | #include "llvm/BinaryFormat/Dwarf.h" | |||
28 | #include "llvm/BinaryFormat/MachO.h" | |||
29 | #include "llvm/BinaryFormat/Swift.h" | |||
30 | #include "llvm/CodeGen/AccelTable.h" | |||
31 | #include "llvm/CodeGen/AsmPrinter.h" | |||
32 | #include "llvm/CodeGen/DIE.h" | |||
33 | #include "llvm/CodeGen/NonRelocatableStringpool.h" | |||
34 | #include "llvm/Config/config.h" | |||
35 | #include "llvm/DWARFLinker/DWARFLinkerDeclContext.h" | |||
36 | #include "llvm/DebugInfo/DIContext.h" | |||
37 | #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" | |||
38 | #include "llvm/DebugInfo/DWARF/DWARFContext.h" | |||
39 | #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" | |||
40 | #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" | |||
41 | #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" | |||
42 | #include "llvm/DebugInfo/DWARF/DWARFDie.h" | |||
43 | #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" | |||
44 | #include "llvm/DebugInfo/DWARF/DWARFSection.h" | |||
45 | #include "llvm/DebugInfo/DWARF/DWARFUnit.h" | |||
46 | #include "llvm/MC/MCAsmBackend.h" | |||
47 | #include "llvm/MC/MCAsmInfo.h" | |||
48 | #include "llvm/MC/MCCodeEmitter.h" | |||
49 | #include "llvm/MC/MCContext.h" | |||
50 | #include "llvm/MC/MCDwarf.h" | |||
51 | #include "llvm/MC/MCInstrInfo.h" | |||
52 | #include "llvm/MC/MCObjectFileInfo.h" | |||
53 | #include "llvm/MC/MCObjectWriter.h" | |||
54 | #include "llvm/MC/MCRegisterInfo.h" | |||
55 | #include "llvm/MC/MCSection.h" | |||
56 | #include "llvm/MC/MCStreamer.h" | |||
57 | #include "llvm/MC/MCSubtargetInfo.h" | |||
58 | #include "llvm/MC/MCTargetOptions.h" | |||
59 | #include "llvm/MC/MCTargetOptionsCommandFlags.h" | |||
60 | #include "llvm/MC/TargetRegistry.h" | |||
61 | #include "llvm/Object/MachO.h" | |||
62 | #include "llvm/Object/ObjectFile.h" | |||
63 | #include "llvm/Object/SymbolicFile.h" | |||
64 | #include "llvm/Support/Allocator.h" | |||
65 | #include "llvm/Support/Casting.h" | |||
66 | #include "llvm/Support/Compiler.h" | |||
67 | #include "llvm/Support/DJB.h" | |||
68 | #include "llvm/Support/DataExtractor.h" | |||
69 | #include "llvm/Support/Error.h" | |||
70 | #include "llvm/Support/ErrorHandling.h" | |||
71 | #include "llvm/Support/ErrorOr.h" | |||
72 | #include "llvm/Support/FileSystem.h" | |||
73 | #include "llvm/Support/Format.h" | |||
74 | #include "llvm/Support/LEB128.h" | |||
75 | #include "llvm/Support/MathExtras.h" | |||
76 | #include "llvm/Support/MemoryBuffer.h" | |||
77 | #include "llvm/Support/Path.h" | |||
78 | #include "llvm/Support/ThreadPool.h" | |||
79 | #include "llvm/Support/ToolOutputFile.h" | |||
80 | #include "llvm/Support/WithColor.h" | |||
81 | #include "llvm/Support/raw_ostream.h" | |||
82 | #include "llvm/Target/TargetMachine.h" | |||
83 | #include "llvm/Target/TargetOptions.h" | |||
84 | #include "llvm/TargetParser/Triple.h" | |||
85 | #include <algorithm> | |||
86 | #include <cassert> | |||
87 | #include <cinttypes> | |||
88 | #include <climits> | |||
89 | #include <cstdint> | |||
90 | #include <cstdlib> | |||
91 | #include <cstring> | |||
92 | #include <limits> | |||
93 | #include <map> | |||
94 | #include <memory> | |||
95 | #include <optional> | |||
96 | #include <string> | |||
97 | #include <system_error> | |||
98 | #include <tuple> | |||
99 | #include <utility> | |||
100 | #include <vector> | |||
101 | ||||
102 | namespace llvm { | |||
103 | ||||
104 | static mc::RegisterMCTargetOptionsFlags MOF; | |||
105 | ||||
106 | namespace dsymutil { | |||
107 | ||||
108 | static void dumpDIE(const DWARFDie *DIE, bool Verbose) { | |||
109 | if (!DIE || !Verbose) | |||
110 | return; | |||
111 | ||||
112 | DIDumpOptions DumpOpts; | |||
113 | DumpOpts.ChildRecurseDepth = 0; | |||
114 | DumpOpts.Verbose = Verbose; | |||
115 | ||||
116 | WithColor::note() << " in DIE:\n"; | |||
117 | DIE->dump(errs(), 6 /* Indent */, DumpOpts); | |||
118 | } | |||
119 | ||||
120 | /// Report a warning to the user, optionally including information about a | |||
121 | /// specific \p DIE related to the warning. | |||
122 | void DwarfLinkerForBinary::reportWarning(Twine Warning, Twine Context, | |||
123 | const DWARFDie *DIE) const { | |||
124 | std::lock_guard<std::mutex> Guard(ErrorHandlerMutex); | |||
125 | warn(Warning, Context); | |||
126 | dumpDIE(DIE, Options.Verbose); | |||
127 | } | |||
128 | ||||
129 | void DwarfLinkerForBinary::reportError(Twine Error, Twine Context, | |||
130 | const DWARFDie *DIE) const { | |||
131 | std::lock_guard<std::mutex> Guard(ErrorHandlerMutex); | |||
132 | error(Error, Context); | |||
133 | dumpDIE(DIE, Options.Verbose); | |||
134 | } | |||
135 | ||||
136 | bool DwarfLinkerForBinary::createStreamer(const Triple &TheTriple, | |||
137 | raw_fd_ostream &OutFile) { | |||
138 | if (Options.NoOutput) | |||
139 | return true; | |||
140 | ||||
141 | Streamer = std::make_unique<DwarfStreamer>( | |||
142 | Options.FileType, OutFile, Options.Translator, | |||
143 | [&](const Twine &Error, StringRef Context, const DWARFDie *) { | |||
144 | reportError(Error, Context); | |||
145 | }, | |||
146 | [&](const Twine &Warning, StringRef Context, const DWARFDie *) { | |||
147 | reportWarning(Warning, Context); | |||
148 | }); | |||
149 | return Streamer->init(TheTriple, "__DWARF"); | |||
150 | } | |||
151 | ||||
152 | ErrorOr<const object::ObjectFile &> | |||
153 | DwarfLinkerForBinary::loadObject(const DebugMapObject &Obj, | |||
154 | const Triple &Triple) { | |||
155 | auto ObjectEntry = | |||
156 | BinHolder.getObjectEntry(Obj.getObjectFilename(), Obj.getTimestamp()); | |||
157 | if (!ObjectEntry) { | |||
158 | auto Err = ObjectEntry.takeError(); | |||
159 | reportWarning(Twine(Obj.getObjectFilename()) + ": " + | |||
160 | toString(std::move(Err)), | |||
161 | Obj.getObjectFilename()); | |||
162 | return errorToErrorCode(std::move(Err)); | |||
| ||||
163 | } | |||
164 | ||||
165 | auto Object = ObjectEntry->getObject(Triple); | |||
166 | if (!Object) { | |||
167 | auto Err = Object.takeError(); | |||
168 | reportWarning(Twine(Obj.getObjectFilename()) + ": " + | |||
169 | toString(std::move(Err)), | |||
170 | Obj.getObjectFilename()); | |||
171 | return errorToErrorCode(std::move(Err)); | |||
172 | } | |||
173 | ||||
174 | return *Object; | |||
175 | } | |||
176 | ||||
177 | static Error remarksErrorHandler(const DebugMapObject &DMO, | |||
178 | DwarfLinkerForBinary &Linker, | |||
179 | std::unique_ptr<FileError> FE) { | |||
180 | bool IsArchive = DMO.getObjectFilename().endswith(")"); | |||
181 | // Don't report errors for missing remark files from static | |||
182 | // archives. | |||
183 | if (!IsArchive) | |||
184 | return Error(std::move(FE)); | |||
185 | ||||
186 | std::string Message = FE->message(); | |||
187 | Error E = FE->takeError(); | |||
188 | Error NewE = handleErrors(std::move(E), [&](std::unique_ptr<ECError> EC) { | |||
189 | if (EC->convertToErrorCode() != std::errc::no_such_file_or_directory) | |||
190 | return Error(std::move(EC)); | |||
191 | ||||
192 | Linker.reportWarning(Message, DMO.getObjectFilename()); | |||
193 | return Error(Error::success()); | |||
194 | }); | |||
195 | ||||
196 | if (!NewE) | |||
197 | return Error::success(); | |||
198 | ||||
199 | return createFileError(FE->getFileName(), std::move(NewE)); | |||
200 | } | |||
201 | ||||
202 | static Error emitRemarks(const LinkOptions &Options, StringRef BinaryPath, | |||
203 | StringRef ArchName, const remarks::RemarkLinker &RL) { | |||
204 | // Make sure we don't create the directories and the file if there is nothing | |||
205 | // to serialize. | |||
206 | if (RL.empty()) | |||
207 | return Error::success(); | |||
208 | ||||
209 | SmallString<128> InputPath; | |||
210 | SmallString<128> Path; | |||
211 | // Create the "Remarks" directory in the "Resources" directory. | |||
212 | sys::path::append(Path, *Options.ResourceDir, "Remarks"); | |||
213 | if (std::error_code EC = sys::fs::create_directories(Path.str(), true, | |||
214 | sys::fs::perms::all_all)) | |||
215 | return errorCodeToError(EC); | |||
216 | ||||
217 | // Append the file name. | |||
218 | // For fat binaries, also append a dash and the architecture name. | |||
219 | sys::path::append(Path, sys::path::filename(BinaryPath)); | |||
220 | if (Options.NumDebugMaps > 1) { | |||
221 | // More than one debug map means we have a fat binary. | |||
222 | Path += '-'; | |||
223 | Path += ArchName; | |||
224 | } | |||
225 | ||||
226 | std::error_code EC; | |||
227 | raw_fd_ostream OS(Options.NoOutput ? "-" : Path.str(), EC, | |||
228 | Options.RemarksFormat == remarks::Format::Bitstream | |||
229 | ? sys::fs::OF_None | |||
230 | : sys::fs::OF_Text); | |||
231 | if (EC) | |||
232 | return errorCodeToError(EC); | |||
233 | ||||
234 | if (Error E = RL.serialize(OS, Options.RemarksFormat)) | |||
235 | return E; | |||
236 | ||||
237 | return Error::success(); | |||
238 | } | |||
239 | ||||
240 | ErrorOr<DWARFFile &> | |||
241 | DwarfLinkerForBinary::loadObject(const DebugMapObject &Obj, | |||
242 | const DebugMap &DebugMap, | |||
243 | remarks::RemarkLinker &RL) { | |||
244 | auto ErrorOrObj = loadObject(Obj, DebugMap.getTriple()); | |||
245 | ||||
246 | if (ErrorOrObj) { | |||
247 | ContextForLinking.push_back( | |||
248 | std::unique_ptr<DWARFContext>(DWARFContext::create(*ErrorOrObj))); | |||
249 | AddressMapForLinking.push_back( | |||
250 | std::make_unique<AddressManager>(*this, *ErrorOrObj, Obj)); | |||
251 | ||||
252 | ObjectsForLinking.push_back(std::make_unique<DWARFFile>( | |||
253 | Obj.getObjectFilename(), ContextForLinking.back().get(), | |||
254 | AddressMapForLinking.back().get(), | |||
255 | Obj.empty() ? Obj.getWarnings() : EmptyWarnings)); | |||
256 | ||||
257 | Error E = RL.link(*ErrorOrObj); | |||
258 | if (Error NewE = handleErrors( | |||
259 | std::move(E), [&](std::unique_ptr<FileError> EC) -> Error { | |||
260 | return remarksErrorHandler(Obj, *this, std::move(EC)); | |||
261 | })) | |||
262 | return errorToErrorCode(std::move(NewE)); | |||
263 | ||||
264 | return *ObjectsForLinking.back(); | |||
265 | } | |||
266 | ||||
267 | return ErrorOrObj.getError(); | |||
268 | } | |||
269 | ||||
270 | static bool binaryHasStrippableSwiftReflectionSections( | |||
271 | const DebugMap &Map, const LinkOptions &Options, BinaryHolder &BinHolder) { | |||
272 | // If the input binary has strippable swift5 reflection sections, there is no | |||
273 | // need to copy them to the .dSYM. Only copy them for binaries where the | |||
274 | // linker omitted the reflection metadata. | |||
275 | if (!Map.getBinaryPath().empty() && | |||
276 | Options.FileType == OutputFileType::Object) { | |||
277 | ||||
278 | auto ObjectEntry = BinHolder.getObjectEntry(Map.getBinaryPath()); | |||
279 | // If ObjectEntry or Object has an error, no binary exists, therefore no | |||
280 | // reflection sections exist. | |||
281 | if (!ObjectEntry) { | |||
282 | // Any errors will be diagnosed later in the main loop, ignore them here. | |||
283 | llvm::consumeError(ObjectEntry.takeError()); | |||
284 | return false; | |||
285 | } | |||
286 | ||||
287 | auto Object = | |||
288 | ObjectEntry->getObjectAs<object::MachOObjectFile>(Map.getTriple()); | |||
289 | if (!Object) { | |||
290 | // Any errors will be diagnosed later in the main loop, ignore them here. | |||
291 | llvm::consumeError(Object.takeError()); | |||
292 | return false; | |||
293 | } | |||
294 | ||||
295 | for (auto &Section : Object->sections()) { | |||
296 | llvm::Expected<llvm::StringRef> NameOrErr = | |||
297 | Object->getSectionName(Section.getRawDataRefImpl()); | |||
298 | if (!NameOrErr) { | |||
299 | llvm::consumeError(NameOrErr.takeError()); | |||
300 | continue; | |||
301 | } | |||
302 | NameOrErr->consume_back("__TEXT"); | |||
303 | auto ReflectionSectionKind = | |||
304 | Object->mapReflectionSectionNameToEnumValue(*NameOrErr); | |||
305 | if (Object->isReflectionSectionStrippable(ReflectionSectionKind)) { | |||
306 | return true; | |||
307 | } | |||
308 | } | |||
309 | } | |||
310 | return false; | |||
311 | } | |||
312 | ||||
313 | /// Calculate the start of the strippable swift reflection sections in Dwarf. | |||
314 | /// Note that there's an assumption that the reflection sections will appear | |||
315 | /// in alphabetic order. | |||
316 | static std::vector<uint64_t> | |||
317 | calculateStartOfStrippableReflectionSections(const DebugMap &Map) { | |||
318 | using llvm::binaryformat::Swift5ReflectionSectionKind; | |||
319 | uint64_t AssocTySize = 0; | |||
320 | uint64_t FieldMdSize = 0; | |||
321 | for (const auto &Obj : Map.objects()) { | |||
322 | auto OF = | |||
323 | llvm::object::ObjectFile::createObjectFile(Obj->getObjectFilename()); | |||
324 | if (!OF) { | |||
325 | llvm::consumeError(OF.takeError()); | |||
326 | continue; | |||
327 | } | |||
328 | if (auto *MO = dyn_cast<llvm::object::MachOObjectFile>(OF->getBinary())) { | |||
329 | for (auto &Section : MO->sections()) { | |||
330 | llvm::Expected<llvm::StringRef> NameOrErr = | |||
331 | MO->getSectionName(Section.getRawDataRefImpl()); | |||
332 | if (!NameOrErr) { | |||
333 | llvm::consumeError(NameOrErr.takeError()); | |||
334 | continue; | |||
335 | } | |||
336 | NameOrErr->consume_back("__TEXT"); | |||
337 | auto ReflSectionKind = | |||
338 | MO->mapReflectionSectionNameToEnumValue(*NameOrErr); | |||
339 | switch (ReflSectionKind) { | |||
340 | case Swift5ReflectionSectionKind::assocty: | |||
341 | AssocTySize += Section.getSize(); | |||
342 | break; | |||
343 | case Swift5ReflectionSectionKind::fieldmd: | |||
344 | FieldMdSize += Section.getSize(); | |||
345 | break; | |||
346 | default: | |||
347 | break; | |||
348 | } | |||
349 | } | |||
350 | } | |||
351 | } | |||
352 | // Initialize the vector with enough space to fit every reflection section | |||
353 | // kind. | |||
354 | std::vector<uint64_t> SectionToOffset(Swift5ReflectionSectionKind::last, 0); | |||
355 | SectionToOffset[Swift5ReflectionSectionKind::assocty] = 0; | |||
356 | SectionToOffset[Swift5ReflectionSectionKind::fieldmd] = | |||
357 | llvm::alignTo(AssocTySize, 4); | |||
358 | SectionToOffset[Swift5ReflectionSectionKind::reflstr] = llvm::alignTo( | |||
359 | SectionToOffset[Swift5ReflectionSectionKind::fieldmd] + FieldMdSize, 4); | |||
360 | ||||
361 | return SectionToOffset; | |||
362 | } | |||
363 | ||||
364 | void DwarfLinkerForBinary::collectRelocationsToApplyToSwiftReflectionSections( | |||
365 | const object::SectionRef &Section, StringRef &Contents, | |||
366 | const llvm::object::MachOObjectFile *MO, | |||
367 | const std::vector<uint64_t> &SectionToOffsetInDwarf, | |||
368 | const llvm::dsymutil::DebugMapObject *Obj, | |||
369 | std::vector<MachOUtils::DwarfRelocationApplicationInfo> &RelocationsToApply) | |||
370 | const { | |||
371 | for (auto It = Section.relocation_begin(); It != Section.relocation_end(); | |||
372 | ++It) { | |||
373 | object::DataRefImpl RelocDataRef = It->getRawDataRefImpl(); | |||
374 | MachO::any_relocation_info MachOReloc = MO->getRelocation(RelocDataRef); | |||
375 | ||||
376 | if (!object::MachOObjectFile::isMachOPairedReloc( | |||
377 | MO->getAnyRelocationType(MachOReloc), MO->getArch())) { | |||
378 | reportWarning( | |||
379 | "Unimplemented relocation type in strippable reflection section ", | |||
380 | Obj->getObjectFilename()); | |||
381 | continue; | |||
382 | } | |||
383 | ||||
384 | auto CalculateAddressOfSymbolInDwarfSegment = | |||
385 | [&]() -> std::optional<int64_t> { | |||
386 | auto Symbol = It->getSymbol(); | |||
387 | auto SymbolAbsoluteAddress = Symbol->getAddress(); | |||
388 | if (!SymbolAbsoluteAddress) | |||
389 | return {}; | |||
390 | auto Section = Symbol->getSection(); | |||
391 | if (!Section) { | |||
392 | llvm::consumeError(Section.takeError()); | |||
393 | return {}; | |||
394 | } | |||
395 | ||||
396 | if ((*Section)->getObject()->section_end() == *Section) | |||
397 | return {}; | |||
398 | ||||
399 | auto SectionStart = (*Section)->getAddress(); | |||
400 | auto SymbolAddressInSection = *SymbolAbsoluteAddress - SectionStart; | |||
401 | auto SectionName = (*Section)->getName(); | |||
402 | if (!SectionName) | |||
403 | return {}; | |||
404 | auto ReflSectionKind = | |||
405 | MO->mapReflectionSectionNameToEnumValue(*SectionName); | |||
406 | ||||
407 | int64_t SectionStartInLinkedBinary = | |||
408 | SectionToOffsetInDwarf[ReflSectionKind]; | |||
409 | ||||
410 | auto Addr = SectionStartInLinkedBinary + SymbolAddressInSection; | |||
411 | return Addr; | |||
412 | }; | |||
413 | ||||
414 | // The first symbol should always be in the section we're currently | |||
415 | // iterating over. | |||
416 | auto FirstSymbolAddress = CalculateAddressOfSymbolInDwarfSegment(); | |||
417 | ++It; | |||
418 | ||||
419 | bool ShouldSubtractDwarfVM = false; | |||
420 | // For the second symbol there are two possibilities. | |||
421 | std::optional<int64_t> SecondSymbolAddress; | |||
422 | auto Sym = It->getSymbol(); | |||
423 | if (Sym != MO->symbol_end()) { | |||
424 | Expected<StringRef> SymbolName = Sym->getName(); | |||
425 | if (SymbolName) { | |||
426 | if (const auto *Mapping = Obj->lookupSymbol(*SymbolName)) { | |||
427 | // First possibility: the symbol exists in the binary, and exists in a | |||
428 | // non-strippable section (for example, typeref, or __TEXT,__const), | |||
429 | // in which case we look up its address in the binary, which dsymutil | |||
430 | // will copy verbatim. | |||
431 | SecondSymbolAddress = Mapping->getValue().BinaryAddress; | |||
432 | // Since the symbols live in different segments, we have to substract | |||
433 | // the start of the Dwarf's vmaddr so the value calculated points to | |||
434 | // the correct place. | |||
435 | ShouldSubtractDwarfVM = true; | |||
436 | } | |||
437 | } | |||
438 | } | |||
439 | ||||
440 | if (!SecondSymbolAddress) { | |||
441 | // Second possibility, this symbol is not present in the main binary, and | |||
442 | // must be in one of the strippable sections (for example, reflstr). | |||
443 | // Calculate its address in the same way as we did the first one. | |||
444 | SecondSymbolAddress = CalculateAddressOfSymbolInDwarfSegment(); | |||
445 | } | |||
446 | ||||
447 | if (!FirstSymbolAddress || !SecondSymbolAddress) | |||
448 | continue; | |||
449 | ||||
450 | auto SectionName = Section.getName(); | |||
451 | if (!SectionName) | |||
452 | continue; | |||
453 | ||||
454 | int32_t Addend; | |||
455 | memcpy(&Addend, Contents.data() + It->getOffset(), sizeof(int32_t)); | |||
456 | int32_t Value = (*SecondSymbolAddress + Addend) - *FirstSymbolAddress; | |||
457 | auto ReflSectionKind = | |||
458 | MO->mapReflectionSectionNameToEnumValue(*SectionName); | |||
459 | uint64_t AddressFromDwarfVM = | |||
460 | SectionToOffsetInDwarf[ReflSectionKind] + It->getOffset(); | |||
461 | RelocationsToApply.emplace_back(AddressFromDwarfVM, Value, | |||
462 | ShouldSubtractDwarfVM); | |||
463 | } | |||
464 | } | |||
465 | ||||
466 | Error DwarfLinkerForBinary::copySwiftInterfaces(StringRef Architecture) const { | |||
467 | std::error_code EC; | |||
468 | SmallString<128> InputPath; | |||
469 | SmallString<128> Path; | |||
470 | sys::path::append(Path, *Options.ResourceDir, "Swift", Architecture); | |||
471 | if ((EC = sys::fs::create_directories(Path.str(), true, | |||
472 | sys::fs::perms::all_all))) | |||
473 | return make_error<StringError>( | |||
474 | "cannot create directory: " + toString(errorCodeToError(EC)), EC); | |||
475 | unsigned BaseLength = Path.size(); | |||
476 | ||||
477 | for (auto &I : ParseableSwiftInterfaces) { | |||
478 | StringRef ModuleName = I.first; | |||
479 | StringRef InterfaceFile = I.second; | |||
480 | if (!Options.PrependPath.empty()) { | |||
481 | InputPath.clear(); | |||
482 | sys::path::append(InputPath, Options.PrependPath, InterfaceFile); | |||
483 | InterfaceFile = InputPath; | |||
484 | } | |||
485 | sys::path::append(Path, ModuleName); | |||
486 | Path.append(".swiftinterface"); | |||
487 | if (Options.Verbose) | |||
488 | outs() << "copy parseable Swift interface " << InterfaceFile << " -> " | |||
489 | << Path.str() << '\n'; | |||
490 | ||||
491 | // copy_file attempts an APFS clone first, so this should be cheap. | |||
492 | if ((EC = sys::fs::copy_file(InterfaceFile, Path.str()))) | |||
493 | reportWarning(Twine("cannot copy parseable Swift interface ") + | |||
494 | InterfaceFile + ": " + toString(errorCodeToError(EC))); | |||
495 | Path.resize(BaseLength); | |||
496 | } | |||
497 | return Error::success(); | |||
498 | } | |||
499 | ||||
500 | void DwarfLinkerForBinary::copySwiftReflectionMetadata( | |||
501 | const llvm::dsymutil::DebugMapObject *Obj, DwarfStreamer *Streamer, | |||
502 | std::vector<uint64_t> &SectionToOffsetInDwarf, | |||
503 | std::vector<MachOUtils::DwarfRelocationApplicationInfo> | |||
504 | &RelocationsToApply) { | |||
505 | using binaryformat::Swift5ReflectionSectionKind; | |||
506 | auto OF = | |||
507 | llvm::object::ObjectFile::createObjectFile(Obj->getObjectFilename()); | |||
508 | if (!OF) { | |||
509 | llvm::consumeError(OF.takeError()); | |||
510 | return; | |||
511 | } | |||
512 | if (auto *MO = dyn_cast<llvm::object::MachOObjectFile>(OF->getBinary())) { | |||
513 | // Collect the swift reflection sections before emitting them. This is | |||
514 | // done so we control the order they're emitted. | |||
515 | std::array<std::optional<object::SectionRef>, | |||
516 | Swift5ReflectionSectionKind::last + 1> | |||
517 | SwiftSections; | |||
518 | for (auto &Section : MO->sections()) { | |||
519 | llvm::Expected<llvm::StringRef> NameOrErr = | |||
520 | MO->getSectionName(Section.getRawDataRefImpl()); | |||
521 | if (!NameOrErr) { | |||
522 | llvm::consumeError(NameOrErr.takeError()); | |||
523 | continue; | |||
524 | } | |||
525 | NameOrErr->consume_back("__TEXT"); | |||
526 | auto ReflSectionKind = | |||
527 | MO->mapReflectionSectionNameToEnumValue(*NameOrErr); | |||
528 | if (MO->isReflectionSectionStrippable(ReflSectionKind)) | |||
529 | SwiftSections[ReflSectionKind] = Section; | |||
530 | } | |||
531 | // Make sure we copy the sections in alphabetic order. | |||
532 | auto SectionKindsToEmit = {Swift5ReflectionSectionKind::assocty, | |||
533 | Swift5ReflectionSectionKind::fieldmd, | |||
534 | Swift5ReflectionSectionKind::reflstr}; | |||
535 | for (auto SectionKind : SectionKindsToEmit) { | |||
536 | if (!SwiftSections[SectionKind]) | |||
537 | continue; | |||
538 | auto &Section = *SwiftSections[SectionKind]; | |||
539 | llvm::Expected<llvm::StringRef> SectionContents = Section.getContents(); | |||
540 | if (!SectionContents) | |||
541 | continue; | |||
542 | const auto *MO = | |||
543 | llvm::cast<llvm::object::MachOObjectFile>(Section.getObject()); | |||
544 | collectRelocationsToApplyToSwiftReflectionSections( | |||
545 | Section, *SectionContents, MO, SectionToOffsetInDwarf, Obj, | |||
546 | RelocationsToApply); | |||
547 | // Update the section start with the current section's contribution, so | |||
548 | // the next section we copy from a different .o file points to the correct | |||
549 | // place. | |||
550 | SectionToOffsetInDwarf[SectionKind] += Section.getSize(); | |||
551 | Streamer->emitSwiftReflectionSection(SectionKind, *SectionContents, | |||
552 | Section.getAlignment().value(), | |||
553 | Section.getSize()); | |||
554 | } | |||
555 | } | |||
556 | } | |||
557 | ||||
558 | bool DwarfLinkerForBinary::link(const DebugMap &Map) { | |||
559 | if (!createStreamer(Map.getTriple(), OutFile)) | |||
560 | return false; | |||
561 | ||||
562 | ObjectsForLinking.clear(); | |||
563 | ContextForLinking.clear(); | |||
564 | AddressMapForLinking.clear(); | |||
565 | ||||
566 | DebugMap DebugMap(Map.getTriple(), Map.getBinaryPath()); | |||
567 | ||||
568 | DWARFLinker GeneralLinker(Streamer.get(), DwarfLinkerClient::Dsymutil); | |||
569 | ||||
570 | remarks::RemarkLinker RL; | |||
571 | if (!Options.RemarksPrependPath.empty()) | |||
572 | RL.setExternalFilePrependPath(Options.RemarksPrependPath); | |||
573 | GeneralLinker.setObjectPrefixMap(&Options.ObjectPrefixMap); | |||
574 | ||||
575 | std::function<StringRef(StringRef)> TranslationLambda = [&](StringRef Input) { | |||
576 | assert(Options.Translator)(static_cast <bool> (Options.Translator) ? void (0) : __assert_fail ("Options.Translator", "llvm/tools/dsymutil/DwarfLinkerForBinary.cpp" , 576, __extension__ __PRETTY_FUNCTION__)); | |||
577 | return Options.Translator(Input); | |||
578 | }; | |||
579 | ||||
580 | GeneralLinker.setVerbosity(Options.Verbose); | |||
581 | GeneralLinker.setStatistics(Options.Statistics); | |||
582 | GeneralLinker.setVerifyInputDWARF(Options.VerifyInputDWARF); | |||
583 | GeneralLinker.setNoOutput(Options.NoOutput); | |||
584 | GeneralLinker.setNoODR(Options.NoODR); | |||
585 | GeneralLinker.setUpdate(Options.Update); | |||
586 | GeneralLinker.setNumThreads(Options.Threads); | |||
587 | GeneralLinker.setPrependPath(Options.PrependPath); | |||
588 | GeneralLinker.setKeepFunctionForStatic(Options.KeepFunctionForStatic); | |||
589 | if (Options.Translator) | |||
590 | GeneralLinker.setStringsTranslator(TranslationLambda); | |||
591 | GeneralLinker.setWarningHandler( | |||
592 | [&](const Twine &Warning, StringRef Context, const DWARFDie *DIE) { | |||
593 | reportWarning(Warning, Context, DIE); | |||
594 | }); | |||
595 | GeneralLinker.setErrorHandler( | |||
596 | [&](const Twine &Error, StringRef Context, const DWARFDie *DIE) { | |||
597 | reportError(Error, Context, DIE); | |||
598 | }); | |||
599 | GeneralLinker.setInputVerificationHandler([&](const DWARFFile &File) { | |||
600 | reportWarning("input verification failed", File.FileName); | |||
601 | HasVerificationErrors = true; | |||
602 | }); | |||
603 | objFileLoader Loader = [&DebugMap, &RL, | |||
604 | this](StringRef ContainerName, | |||
605 | StringRef Path) -> ErrorOr<DWARFFile &> { | |||
606 | auto &Obj = DebugMap.addDebugMapObject( | |||
607 | Path, sys::TimePoint<std::chrono::seconds>(), MachO::N_OSO); | |||
608 | ||||
609 | if (auto ErrorOrObj = loadObject(Obj, DebugMap, RL)) { | |||
| ||||
610 | return *ErrorOrObj; | |||
611 | } else { | |||
612 | // Try and emit more helpful warnings by applying some heuristics. | |||
613 | StringRef ObjFile = ContainerName; | |||
614 | bool IsClangModule = sys::path::extension(Path).equals(".pcm"); | |||
615 | bool IsArchive = ObjFile.endswith(")"); | |||
616 | ||||
617 | if (IsClangModule) { | |||
618 | StringRef ModuleCacheDir = sys::path::parent_path(Path); | |||
619 | if (sys::fs::exists(ModuleCacheDir)) { | |||
620 | // If the module's parent directory exists, we assume that the | |||
621 | // module cache has expired and was pruned by clang. A more | |||
622 | // adventurous dsymutil would invoke clang to rebuild the module | |||
623 | // now. | |||
624 | if (!ModuleCacheHintDisplayed) { | |||
625 | WithColor::note() | |||
626 | << "The clang module cache may have expired since " | |||
627 | "this object file was built. Rebuilding the " | |||
628 | "object file will rebuild the module cache.\n"; | |||
629 | ModuleCacheHintDisplayed = true; | |||
630 | } | |||
631 | } else if (IsArchive) { | |||
632 | // If the module cache directory doesn't exist at all and the | |||
633 | // object file is inside a static library, we assume that the | |||
634 | // static library was built on a different machine. We don't want | |||
635 | // to discourage module debugging for convenience libraries within | |||
636 | // a project though. | |||
637 | if (!ArchiveHintDisplayed) { | |||
638 | WithColor::note() | |||
639 | << "Linking a static library that was built with " | |||
640 | "-gmodules, but the module cache was not found. " | |||
641 | "Redistributable static libraries should never be " | |||
642 | "built with module debugging enabled. The debug " | |||
643 | "experience will be degraded due to incomplete " | |||
644 | "debug information.\n"; | |||
645 | ArchiveHintDisplayed = true; | |||
646 | } | |||
647 | } | |||
648 | } | |||
649 | ||||
650 | return ErrorOrObj.getError(); | |||
651 | } | |||
652 | ||||
653 | llvm_unreachable("Unhandled DebugMap object")::llvm::llvm_unreachable_internal("Unhandled DebugMap object" , "llvm/tools/dsymutil/DwarfLinkerForBinary.cpp", 653); | |||
654 | }; | |||
655 | GeneralLinker.setSwiftInterfacesMap(&ParseableSwiftInterfaces); | |||
656 | bool ReflectionSectionsPresentInBinary = false; | |||
657 | // If there is no output specified, no point in checking the binary for swift5 | |||
658 | // reflection sections. | |||
659 | if (!Options.NoOutput) { | |||
660 | ReflectionSectionsPresentInBinary = | |||
661 | binaryHasStrippableSwiftReflectionSections(Map, Options, BinHolder); | |||
662 | } | |||
663 | ||||
664 | std::vector<MachOUtils::DwarfRelocationApplicationInfo> RelocationsToApply; | |||
665 | if (!Options.NoOutput && !ReflectionSectionsPresentInBinary) { | |||
666 | auto SectionToOffsetInDwarf = | |||
667 | calculateStartOfStrippableReflectionSections(Map); | |||
668 | for (const auto &Obj : Map.objects()) | |||
669 | copySwiftReflectionMetadata(Obj.get(), Streamer.get(), | |||
670 | SectionToOffsetInDwarf, RelocationsToApply); | |||
671 | } | |||
672 | ||||
673 | uint16_t MaxDWARFVersion = 0; | |||
674 | std::function<void(const DWARFUnit &Unit)> OnCUDieLoaded = | |||
675 | [&MaxDWARFVersion](const DWARFUnit &Unit) { | |||
676 | MaxDWARFVersion = std::max(Unit.getVersion(), MaxDWARFVersion); | |||
677 | }; | |||
678 | ||||
679 | for (const auto &Obj : Map.objects()) { | |||
680 | // N_AST objects (swiftmodule files) should get dumped directly into the | |||
681 | // appropriate DWARF section. | |||
682 | if (Obj->getType() == MachO::N_AST) { | |||
683 | if (Options.Verbose) | |||
684 | outs() << "DEBUG MAP OBJECT: " << Obj->getObjectFilename() << "\n"; | |||
685 | ||||
686 | StringRef File = Obj->getObjectFilename(); | |||
687 | auto ErrorOrMem = MemoryBuffer::getFile(File); | |||
688 | if (!ErrorOrMem) { | |||
689 | reportWarning("Could not open '" + File + "'"); | |||
690 | continue; | |||
691 | } | |||
692 | sys::fs::file_status Stat; | |||
693 | if (auto Err = sys::fs::status(File, Stat)) { | |||
694 | reportWarning(Err.message()); | |||
695 | continue; | |||
696 | } | |||
697 | if (!Options.NoTimestamp) { | |||
698 | // The modification can have sub-second precision so we need to cast | |||
699 | // away the extra precision that's not present in the debug map. | |||
700 | auto ModificationTime = | |||
701 | std::chrono::time_point_cast<std::chrono::seconds>( | |||
702 | Stat.getLastModificationTime()); | |||
703 | if (Obj->getTimestamp() != sys::TimePoint<>() && | |||
704 | ModificationTime != Obj->getTimestamp()) { | |||
705 | // Not using the helper here as we can easily stream TimePoint<>. | |||
706 | WithColor::warning() | |||
707 | << File << ": timestamp mismatch between swift interface file (" | |||
708 | << sys::TimePoint<>(ModificationTime) << ") and debug map (" | |||
709 | << sys::TimePoint<>(Obj->getTimestamp()) << ")\n"; | |||
710 | continue; | |||
711 | } | |||
712 | } | |||
713 | ||||
714 | // Copy the module into the .swift_ast section. | |||
715 | if (!Options.NoOutput) | |||
716 | Streamer->emitSwiftAST((*ErrorOrMem)->getBuffer()); | |||
717 | ||||
718 | continue; | |||
719 | } | |||
720 | ||||
721 | if (auto ErrorOrObj = loadObject(*Obj, Map, RL)) | |||
722 | GeneralLinker.addObjectFile(*ErrorOrObj, Loader, OnCUDieLoaded); | |||
723 | else { | |||
724 | ObjectsForLinking.push_back(std::make_unique<DWARFFile>( | |||
725 | Obj->getObjectFilename(), nullptr, nullptr, | |||
726 | Obj->empty() ? Obj->getWarnings() : EmptyWarnings)); | |||
727 | GeneralLinker.addObjectFile(*ObjectsForLinking.back()); | |||
728 | } | |||
729 | } | |||
730 | ||||
731 | // If we haven't seen any CUs, pick an arbitrary valid Dwarf version anyway. | |||
732 | if (MaxDWARFVersion == 0) | |||
733 | MaxDWARFVersion = 3; | |||
734 | ||||
735 | if (Error E = GeneralLinker.setTargetDWARFVersion(MaxDWARFVersion)) | |||
736 | return error(toString(std::move(E))); | |||
737 | ||||
738 | switch (Options.TheAccelTableKind) { | |||
739 | case DsymutilAccelTableKind::Apple: | |||
740 | GeneralLinker.addAccelTableKind(DwarfLinkerAccelTableKind::Apple); | |||
741 | break; | |||
742 | case DsymutilAccelTableKind::Dwarf: | |||
743 | GeneralLinker.addAccelTableKind(DwarfLinkerAccelTableKind::DebugNames); | |||
744 | break; | |||
745 | case DsymutilAccelTableKind::Pub: | |||
746 | GeneralLinker.addAccelTableKind(DwarfLinkerAccelTableKind::Pub); | |||
747 | break; | |||
748 | case DsymutilAccelTableKind::Default: | |||
749 | if (MaxDWARFVersion >= 5) | |||
750 | GeneralLinker.addAccelTableKind(DwarfLinkerAccelTableKind::DebugNames); | |||
751 | else | |||
752 | GeneralLinker.addAccelTableKind(DwarfLinkerAccelTableKind::Apple); | |||
753 | break; | |||
754 | case DsymutilAccelTableKind::None: | |||
755 | // Nothing to do. | |||
756 | break; | |||
757 | } | |||
758 | ||||
759 | // link debug info for loaded object files. | |||
760 | if (Error E = GeneralLinker.link()) | |||
761 | return error(toString(std::move(E))); | |||
762 | ||||
763 | StringRef ArchName = Map.getTriple().getArchName(); | |||
764 | if (Error E = emitRemarks(Options, Map.getBinaryPath(), ArchName, RL)) | |||
765 | return error(toString(std::move(E))); | |||
766 | ||||
767 | if (Options.NoOutput) | |||
768 | return true; | |||
769 | ||||
770 | if (Options.ResourceDir && !ParseableSwiftInterfaces.empty()) { | |||
771 | StringRef ArchName = Triple::getArchTypeName(Map.getTriple().getArch()); | |||
772 | if (auto E = copySwiftInterfaces(ArchName)) | |||
773 | return error(toString(std::move(E))); | |||
774 | } | |||
775 | ||||
776 | if (Map.getTriple().isOSDarwin() && !Map.getBinaryPath().empty() && | |||
777 | Options.FileType == OutputFileType::Object) | |||
778 | return MachOUtils::generateDsymCompanion( | |||
779 | Options.VFS, Map, Options.Translator, | |||
780 | *Streamer->getAsmPrinter().OutStreamer, OutFile, RelocationsToApply); | |||
781 | ||||
782 | Streamer->finish(); | |||
783 | return true; | |||
784 | } | |||
785 | ||||
786 | /// Iterate over the relocations of the given \p Section and | |||
787 | /// store the ones that correspond to debug map entries into the | |||
788 | /// ValidRelocs array. | |||
789 | void DwarfLinkerForBinary::AddressManager::findValidRelocsMachO( | |||
790 | const object::SectionRef &Section, const object::MachOObjectFile &Obj, | |||
791 | const DebugMapObject &DMO, std::vector<ValidReloc> &ValidRelocs) { | |||
792 | Expected<StringRef> ContentsOrErr = Section.getContents(); | |||
793 | if (!ContentsOrErr) { | |||
794 | consumeError(ContentsOrErr.takeError()); | |||
795 | Linker.reportWarning("error reading section", DMO.getObjectFilename()); | |||
796 | return; | |||
797 | } | |||
798 | DataExtractor Data(*ContentsOrErr, Obj.isLittleEndian(), 0); | |||
799 | bool SkipNext = false; | |||
800 | ||||
801 | for (const object::RelocationRef &Reloc : Section.relocations()) { | |||
802 | if (SkipNext) { | |||
803 | SkipNext = false; | |||
804 | continue; | |||
805 | } | |||
806 | ||||
807 | object::DataRefImpl RelocDataRef = Reloc.getRawDataRefImpl(); | |||
808 | MachO::any_relocation_info MachOReloc = Obj.getRelocation(RelocDataRef); | |||
809 | ||||
810 | if (object::MachOObjectFile::isMachOPairedReloc(Obj.getAnyRelocationType(MachOReloc), | |||
811 | Obj.getArch())) { | |||
812 | SkipNext = true; | |||
813 | Linker.reportWarning("unsupported relocation in " + *Section.getName() + | |||
814 | " section.", | |||
815 | DMO.getObjectFilename()); | |||
816 | continue; | |||
817 | } | |||
818 | ||||
819 | unsigned RelocSize = 1 << Obj.getAnyRelocationLength(MachOReloc); | |||
820 | uint64_t Offset64 = Reloc.getOffset(); | |||
821 | if ((RelocSize != 4 && RelocSize != 8)) { | |||
822 | Linker.reportWarning("unsupported relocation in " + *Section.getName() + | |||
823 | " section.", | |||
824 | DMO.getObjectFilename()); | |||
825 | continue; | |||
826 | } | |||
827 | uint64_t OffsetCopy = Offset64; | |||
828 | // Mach-o uses REL relocations, the addend is at the relocation offset. | |||
829 | uint64_t Addend = Data.getUnsigned(&OffsetCopy, RelocSize); | |||
830 | uint64_t SymAddress; | |||
831 | int64_t SymOffset; | |||
832 | ||||
833 | if (Obj.isRelocationScattered(MachOReloc)) { | |||
834 | // The address of the base symbol for scattered relocations is | |||
835 | // stored in the reloc itself. The actual addend will store the | |||
836 | // base address plus the offset. | |||
837 | SymAddress = Obj.getScatteredRelocationValue(MachOReloc); | |||
838 | SymOffset = int64_t(Addend) - SymAddress; | |||
839 | } else { | |||
840 | SymAddress = Addend; | |||
841 | SymOffset = 0; | |||
842 | } | |||
843 | ||||
844 | auto Sym = Reloc.getSymbol(); | |||
845 | if (Sym != Obj.symbol_end()) { | |||
846 | Expected<StringRef> SymbolName = Sym->getName(); | |||
847 | if (!SymbolName) { | |||
848 | consumeError(SymbolName.takeError()); | |||
849 | Linker.reportWarning("error getting relocation symbol name.", | |||
850 | DMO.getObjectFilename()); | |||
851 | continue; | |||
852 | } | |||
853 | if (const auto *Mapping = DMO.lookupSymbol(*SymbolName)) | |||
854 | ValidRelocs.emplace_back(Offset64, RelocSize, Addend, Mapping); | |||
855 | } else if (const auto *Mapping = DMO.lookupObjectAddress(SymAddress)) { | |||
856 | // Do not store the addend. The addend was the address of the symbol in | |||
857 | // the object file, the address in the binary that is stored in the debug | |||
858 | // map doesn't need to be offset. | |||
859 | ValidRelocs.emplace_back(Offset64, RelocSize, SymOffset, Mapping); | |||
860 | } | |||
861 | } | |||
862 | } | |||
863 | ||||
864 | /// Dispatch the valid relocation finding logic to the | |||
865 | /// appropriate handler depending on the object file format. | |||
866 | bool DwarfLinkerForBinary::AddressManager::findValidRelocs( | |||
867 | const object::SectionRef &Section, const object::ObjectFile &Obj, | |||
868 | const DebugMapObject &DMO, std::vector<ValidReloc> &Relocs) { | |||
869 | // Dispatch to the right handler depending on the file type. | |||
870 | if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(&Obj)) | |||
871 | findValidRelocsMachO(Section, *MachOObj, DMO, Relocs); | |||
872 | else | |||
873 | Linker.reportWarning(Twine("unsupported object file type: ") + | |||
874 | Obj.getFileName(), | |||
875 | DMO.getObjectFilename()); | |||
876 | if (Relocs.empty()) | |||
877 | return false; | |||
878 | ||||
879 | // Sort the relocations by offset. We will walk the DIEs linearly in | |||
880 | // the file, this allows us to just keep an index in the relocation | |||
881 | // array that we advance during our walk, rather than resorting to | |||
882 | // some associative container. See DwarfLinkerForBinary::NextValidReloc. | |||
883 | llvm::sort(Relocs); | |||
884 | return true; | |||
885 | } | |||
886 | ||||
887 | /// Look for relocations in the debug_info and debug_addr section that match | |||
888 | /// entries in the debug map. These relocations will drive the Dwarf link by | |||
889 | /// indicating which DIEs refer to symbols present in the linked binary. | |||
890 | /// \returns whether there are any valid relocations in the debug info. | |||
891 | bool DwarfLinkerForBinary::AddressManager::findValidRelocsInDebugSections( | |||
892 | const object::ObjectFile &Obj, const DebugMapObject &DMO) { | |||
893 | // Find the debug_info section. | |||
894 | bool FoundValidRelocs = false; | |||
895 | for (const object::SectionRef &Section : Obj.sections()) { | |||
896 | StringRef SectionName; | |||
897 | if (Expected<StringRef> NameOrErr = Section.getName()) | |||
898 | SectionName = *NameOrErr; | |||
899 | else | |||
900 | consumeError(NameOrErr.takeError()); | |||
901 | ||||
902 | SectionName = SectionName.substr(SectionName.find_first_not_of("._")); | |||
903 | if (SectionName == "debug_info") | |||
904 | FoundValidRelocs |= | |||
905 | findValidRelocs(Section, Obj, DMO, ValidDebugInfoRelocs); | |||
906 | if (SectionName == "debug_addr") | |||
907 | FoundValidRelocs |= | |||
908 | findValidRelocs(Section, Obj, DMO, ValidDebugAddrRelocs); | |||
909 | } | |||
910 | return FoundValidRelocs; | |||
911 | } | |||
912 | ||||
913 | std::vector<DwarfLinkerForBinary::AddressManager::ValidReloc> | |||
914 | DwarfLinkerForBinary::AddressManager::getRelocations( | |||
915 | const std::vector<ValidReloc> &Relocs, uint64_t StartPos, uint64_t EndPos) { | |||
916 | std::vector<DwarfLinkerForBinary::AddressManager::ValidReloc> Res; | |||
917 | ||||
918 | auto CurReloc = partition_point(Relocs, [StartPos](const ValidReloc &Reloc) { | |||
919 | return Reloc.Offset < StartPos; | |||
920 | }); | |||
921 | ||||
922 | while (CurReloc != Relocs.end() && CurReloc->Offset >= StartPos && | |||
923 | CurReloc->Offset < EndPos) { | |||
924 | Res.push_back(*CurReloc); | |||
925 | CurReloc++; | |||
926 | } | |||
927 | ||||
928 | return Res; | |||
929 | } | |||
930 | ||||
931 | void DwarfLinkerForBinary::AddressManager::printReloc(const ValidReloc &Reloc) { | |||
932 | const auto &Mapping = Reloc.Mapping->getValue(); | |||
933 | const uint64_t ObjectAddress = Mapping.ObjectAddress | |||
934 | ? uint64_t(*Mapping.ObjectAddress) | |||
935 | : std::numeric_limits<uint64_t>::max(); | |||
936 | ||||
937 | outs() << "Found valid debug map entry: " << Reloc.Mapping->getKey() << "\t" | |||
938 | << format("0x%016" PRIx64"l" "x" " => 0x%016" PRIx64"l" "x" "\n", ObjectAddress, | |||
939 | uint64_t(Mapping.BinaryAddress)); | |||
940 | } | |||
941 | ||||
942 | int64_t | |||
943 | DwarfLinkerForBinary::AddressManager::getRelocValue(const ValidReloc &Reloc) { | |||
944 | int64_t AddrAdjust = relocate(Reloc); | |||
945 | if (Reloc.Mapping->getValue().ObjectAddress) | |||
946 | AddrAdjust -= uint64_t(*Reloc.Mapping->getValue().ObjectAddress); | |||
947 | return AddrAdjust; | |||
948 | } | |||
949 | ||||
950 | std::optional<int64_t> | |||
951 | DwarfLinkerForBinary::AddressManager::hasValidRelocationAt( | |||
952 | const std::vector<ValidReloc> &AllRelocs, uint64_t StartOffset, | |||
953 | uint64_t EndOffset) { | |||
954 | std::vector<ValidReloc> Relocs = | |||
955 | getRelocations(AllRelocs, StartOffset, EndOffset); | |||
956 | ||||
957 | if (Relocs.size() == 0) | |||
958 | return std::nullopt; | |||
959 | ||||
960 | if (Linker.Options.Verbose) | |||
961 | printReloc(Relocs[0]); | |||
962 | ||||
963 | return getRelocValue(Relocs[0]); | |||
964 | } | |||
965 | ||||
966 | /// Get the starting and ending (exclusive) offset for the | |||
967 | /// attribute with index \p Idx descibed by \p Abbrev. \p Offset is | |||
968 | /// supposed to point to the position of the first attribute described | |||
969 | /// by \p Abbrev. | |||
970 | /// \return [StartOffset, EndOffset) as a pair. | |||
971 | static std::pair<uint64_t, uint64_t> | |||
972 | getAttributeOffsets(const DWARFAbbreviationDeclaration *Abbrev, unsigned Idx, | |||
973 | uint64_t Offset, const DWARFUnit &Unit) { | |||
974 | DataExtractor Data = Unit.getDebugInfoExtractor(); | |||
975 | ||||
976 | for (unsigned I = 0; I < Idx; ++I) | |||
977 | DWARFFormValue::skipValue(Abbrev->getFormByIndex(I), Data, &Offset, | |||
978 | Unit.getFormParams()); | |||
979 | ||||
980 | uint64_t End = Offset; | |||
981 | DWARFFormValue::skipValue(Abbrev->getFormByIndex(Idx), Data, &End, | |||
982 | Unit.getFormParams()); | |||
983 | ||||
984 | return std::make_pair(Offset, End); | |||
985 | } | |||
986 | ||||
987 | std::optional<int64_t> | |||
988 | DwarfLinkerForBinary::AddressManager::getVariableRelocAdjustment( | |||
989 | const DWARFDie &DIE) { | |||
990 | const auto *Abbrev = DIE.getAbbreviationDeclarationPtr(); | |||
991 | ||||
992 | std::optional<uint32_t> LocationIdx = | |||
993 | Abbrev->findAttributeIndex(dwarf::DW_AT_location); | |||
994 | if (!LocationIdx) | |||
995 | return std::nullopt; | |||
996 | ||||
997 | uint64_t Offset = DIE.getOffset() + getULEB128Size(Abbrev->getCode()); | |||
998 | uint64_t LocationOffset, LocationEndOffset; | |||
999 | std::tie(LocationOffset, LocationEndOffset) = | |||
1000 | getAttributeOffsets(Abbrev, *LocationIdx, Offset, *DIE.getDwarfUnit()); | |||
1001 | ||||
1002 | // FIXME: Support relocations debug_addr. | |||
1003 | return hasValidRelocationAt(ValidDebugInfoRelocs, LocationOffset, | |||
1004 | LocationEndOffset); | |||
1005 | } | |||
1006 | ||||
1007 | std::optional<int64_t> | |||
1008 | DwarfLinkerForBinary::AddressManager::getSubprogramRelocAdjustment( | |||
1009 | const DWARFDie &DIE) { | |||
1010 | const auto *Abbrev = DIE.getAbbreviationDeclarationPtr(); | |||
1011 | ||||
1012 | std::optional<uint32_t> LowPcIdx = | |||
1013 | Abbrev->findAttributeIndex(dwarf::DW_AT_low_pc); | |||
1014 | if (!LowPcIdx) | |||
1015 | return std::nullopt; | |||
1016 | ||||
1017 | dwarf::Form Form = Abbrev->getFormByIndex(*LowPcIdx); | |||
1018 | ||||
1019 | switch (Form) { | |||
1020 | case dwarf::DW_FORM_addr: { | |||
1021 | uint64_t Offset = DIE.getOffset() + getULEB128Size(Abbrev->getCode()); | |||
1022 | uint64_t LowPcOffset, LowPcEndOffset; | |||
1023 | std::tie(LowPcOffset, LowPcEndOffset) = | |||
1024 | getAttributeOffsets(Abbrev, *LowPcIdx, Offset, *DIE.getDwarfUnit()); | |||
1025 | return hasValidRelocationAt(ValidDebugInfoRelocs, LowPcOffset, | |||
1026 | LowPcEndOffset); | |||
1027 | } | |||
1028 | case dwarf::DW_FORM_addrx: | |||
1029 | case dwarf::DW_FORM_addrx1: | |||
1030 | case dwarf::DW_FORM_addrx2: | |||
1031 | case dwarf::DW_FORM_addrx3: | |||
1032 | case dwarf::DW_FORM_addrx4: { | |||
1033 | std::optional<DWARFFormValue> AddrValue = DIE.find(dwarf::DW_AT_low_pc); | |||
1034 | if (std::optional<uint64_t> AddrOffsetSectionBase = | |||
1035 | DIE.getDwarfUnit()->getAddrOffsetSectionBase()) { | |||
1036 | uint64_t StartOffset = *AddrOffsetSectionBase + AddrValue->getRawUValue(); | |||
1037 | uint64_t EndOffset = | |||
1038 | StartOffset + DIE.getDwarfUnit()->getAddressByteSize(); | |||
1039 | return hasValidRelocationAt(ValidDebugAddrRelocs, StartOffset, EndOffset); | |||
1040 | } | |||
1041 | ||||
1042 | Linker.reportWarning("no base offset for address table", SrcFileName); | |||
1043 | return std::nullopt; | |||
1044 | } | |||
1045 | default: | |||
1046 | return std::nullopt; | |||
1047 | } | |||
1048 | } | |||
1049 | ||||
1050 | uint64_t | |||
1051 | DwarfLinkerForBinary::AddressManager::relocate(const ValidReloc &Reloc) const { | |||
1052 | return Reloc.Mapping->getValue().BinaryAddress + Reloc.Addend; | |||
1053 | } | |||
1054 | ||||
1055 | /// Apply the valid relocations found by findValidRelocs() to | |||
1056 | /// the buffer \p Data, taking into account that Data is at \p BaseOffset | |||
1057 | /// in the debug_info section. | |||
1058 | /// | |||
1059 | /// Like for findValidRelocs(), this function must be called with | |||
1060 | /// monotonic \p BaseOffset values. | |||
1061 | /// | |||
1062 | /// \returns whether any reloc has been applied. | |||
1063 | bool DwarfLinkerForBinary::AddressManager::applyValidRelocs( | |||
1064 | MutableArrayRef<char> Data, uint64_t BaseOffset, bool IsLittleEndian) { | |||
1065 | std::vector<ValidReloc> Relocs = getRelocations( | |||
1066 | ValidDebugInfoRelocs, BaseOffset, BaseOffset + Data.size()); | |||
1067 | ||||
1068 | for (const ValidReloc &CurReloc : Relocs) { | |||
1069 | assert(CurReloc.Offset - BaseOffset < Data.size())(static_cast <bool> (CurReloc.Offset - BaseOffset < Data .size()) ? void (0) : __assert_fail ("CurReloc.Offset - BaseOffset < Data.size()" , "llvm/tools/dsymutil/DwarfLinkerForBinary.cpp", 1069, __extension__ __PRETTY_FUNCTION__)); | |||
1070 | assert(CurReloc.Offset - BaseOffset + CurReloc.Size <= Data.size())(static_cast <bool> (CurReloc.Offset - BaseOffset + CurReloc .Size <= Data.size()) ? void (0) : __assert_fail ("CurReloc.Offset - BaseOffset + CurReloc.Size <= Data.size()" , "llvm/tools/dsymutil/DwarfLinkerForBinary.cpp", 1070, __extension__ __PRETTY_FUNCTION__)); | |||
1071 | char Buf[8]; | |||
1072 | uint64_t Value = relocate(CurReloc); | |||
1073 | for (unsigned I = 0; I != CurReloc.Size; ++I) { | |||
1074 | unsigned Index = IsLittleEndian ? I : (CurReloc.Size - I - 1); | |||
1075 | Buf[I] = uint8_t(Value >> (Index * 8)); | |||
1076 | } | |||
1077 | assert(CurReloc.Size <= sizeof(Buf))(static_cast <bool> (CurReloc.Size <= sizeof(Buf)) ? void (0) : __assert_fail ("CurReloc.Size <= sizeof(Buf)", "llvm/tools/dsymutil/DwarfLinkerForBinary.cpp", 1077, __extension__ __PRETTY_FUNCTION__)); | |||
1078 | memcpy(&Data[CurReloc.Offset - BaseOffset], Buf, CurReloc.Size); | |||
1079 | } | |||
1080 | ||||
1081 | return Relocs.size() > 0; | |||
1082 | } | |||
1083 | ||||
1084 | } // namespace dsymutil | |||
1085 | } // namespace llvm |
1 | //===- llvm/Support/Error.h - Recoverable error handling --------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file defines an API used to report recoverable errors. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_SUPPORT_ERROR_H |
14 | #define LLVM_SUPPORT_ERROR_H |
15 | |
16 | #include "llvm-c/Error.h" |
17 | #include "llvm/ADT/SmallVector.h" |
18 | #include "llvm/ADT/StringExtras.h" |
19 | #include "llvm/ADT/Twine.h" |
20 | #include "llvm/Config/abi-breaking.h" |
21 | #include "llvm/Support/AlignOf.h" |
22 | #include "llvm/Support/Compiler.h" |
23 | #include "llvm/Support/Debug.h" |
24 | #include "llvm/Support/ErrorHandling.h" |
25 | #include "llvm/Support/ErrorOr.h" |
26 | #include "llvm/Support/Format.h" |
27 | #include "llvm/Support/raw_ostream.h" |
28 | #include <cassert> |
29 | #include <cstdint> |
30 | #include <cstdlib> |
31 | #include <functional> |
32 | #include <memory> |
33 | #include <new> |
34 | #include <optional> |
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 [[nodiscard]] Error { |
157 | // ErrorList needs to be able to yank ErrorInfoBase pointers out of Errors |
158 | // to add to the error list. It can't rely on handleErrors for this, since |
159 | // handleErrors does not support ErrorList handlers. |
160 | friend class ErrorList; |
161 | |
162 | // handleErrors needs to be able to set the Checked flag. |
163 | template <typename... HandlerTs> |
164 | friend Error handleErrors(Error E, HandlerTs &&... Handlers); |
165 | |
166 | // Expected<T> needs to be able to steal the payload when constructed from an |
167 | // error. |
168 | template <typename T> friend class Expected; |
169 | |
170 | // wrap needs to be able to steal the payload. |
171 | friend LLVMErrorRef wrap(Error); |
172 | |
173 | protected: |
174 | /// Create a success value. Prefer using 'Error::success()' for readability |
175 | Error() { |
176 | setPtr(nullptr); |
177 | setChecked(false); |
178 | } |
179 | |
180 | public: |
181 | /// Create a success value. |
182 | static ErrorSuccess success(); |
183 | |
184 | // Errors are not copy-constructable. |
185 | Error(const Error &Other) = delete; |
186 | |
187 | /// Move-construct an error value. The newly constructed error is considered |
188 | /// unchecked, even if the source error had been checked. The original error |
189 | /// becomes a checked Success value, regardless of its original state. |
190 | Error(Error &&Other) { |
191 | setChecked(true); |
192 | *this = std::move(Other); |
193 | } |
194 | |
195 | /// Create an error value. Prefer using the 'make_error' function, but |
196 | /// this constructor can be useful when "re-throwing" errors from handlers. |
197 | Error(std::unique_ptr<ErrorInfoBase> Payload) { |
198 | setPtr(Payload.release()); |
199 | setChecked(false); |
200 | } |
201 | |
202 | // Errors are not copy-assignable. |
203 | Error &operator=(const Error &Other) = delete; |
204 | |
205 | /// Move-assign an error value. The current error must represent success, you |
206 | /// you cannot overwrite an unhandled error. The current error is then |
207 | /// considered unchecked. The source error becomes a checked success value, |
208 | /// regardless of its original state. |
209 | Error &operator=(Error &&Other) { |
210 | // Don't allow overwriting of unchecked values. |
211 | assertIsChecked(); |
212 | setPtr(Other.getPtr()); |
213 | |
214 | // This Error is unchecked, even if the source error was checked. |
215 | setChecked(false); |
216 | |
217 | // Null out Other's payload and set its checked bit. |
218 | Other.setPtr(nullptr); |
219 | Other.setChecked(true); |
220 | |
221 | return *this; |
222 | } |
223 | |
224 | /// Destroy a Error. Fails with a call to abort() if the error is |
225 | /// unchecked. |
226 | ~Error() { |
227 | assertIsChecked(); |
228 | delete getPtr(); |
229 | } |
230 | |
231 | /// Bool conversion. Returns true if this Error is in a failure state, |
232 | /// and false if it is in an accept state. If the error is in a Success state |
233 | /// it will be considered checked. |
234 | explicit operator bool() { |
235 | setChecked(getPtr() == nullptr); |
236 | return getPtr() != nullptr; |
237 | } |
238 | |
239 | /// Check whether one error is a subclass of another. |
240 | template <typename ErrT> bool isA() const { |
241 | return getPtr() && getPtr()->isA(ErrT::classID()); |
242 | } |
243 | |
244 | /// Returns the dynamic class id of this error, or null if this is a success |
245 | /// value. |
246 | const void* dynamicClassID() const { |
247 | if (!getPtr()) |
248 | return nullptr; |
249 | return getPtr()->dynamicClassID(); |
250 | } |
251 | |
252 | private: |
253 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
254 | // assertIsChecked() happens very frequently, but under normal circumstances |
255 | // is supposed to be a no-op. So we want it to be inlined, but having a bunch |
256 | // of debug prints can cause the function to be too large for inlining. So |
257 | // it's important that we define this function out of line so that it can't be |
258 | // inlined. |
259 | [[noreturn]] void fatalUncheckedError() const; |
260 | #endif |
261 | |
262 | void assertIsChecked() { |
263 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
264 | if (LLVM_UNLIKELY(!getChecked() || getPtr())__builtin_expect((bool)(!getChecked() || getPtr()), false)) |
265 | fatalUncheckedError(); |
266 | #endif |
267 | } |
268 | |
269 | ErrorInfoBase *getPtr() const { |
270 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
271 | return reinterpret_cast<ErrorInfoBase*>( |
272 | reinterpret_cast<uintptr_t>(Payload) & |
273 | ~static_cast<uintptr_t>(0x1)); |
274 | #else |
275 | return Payload; |
276 | #endif |
277 | } |
278 | |
279 | void setPtr(ErrorInfoBase *EI) { |
280 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
281 | Payload = reinterpret_cast<ErrorInfoBase*>( |
282 | (reinterpret_cast<uintptr_t>(EI) & |
283 | ~static_cast<uintptr_t>(0x1)) | |
284 | (reinterpret_cast<uintptr_t>(Payload) & 0x1)); |
285 | #else |
286 | Payload = EI; |
287 | #endif |
288 | } |
289 | |
290 | bool getChecked() const { |
291 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
292 | return (reinterpret_cast<uintptr_t>(Payload) & 0x1) == 0; |
293 | #else |
294 | return true; |
295 | #endif |
296 | } |
297 | |
298 | void setChecked(bool V) { |
299 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
300 | Payload = reinterpret_cast<ErrorInfoBase*>( |
301 | (reinterpret_cast<uintptr_t>(Payload) & |
302 | ~static_cast<uintptr_t>(0x1)) | |
303 | (V ? 0 : 1)); |
304 | #endif |
305 | } |
306 | |
307 | std::unique_ptr<ErrorInfoBase> takePayload() { |
308 | std::unique_ptr<ErrorInfoBase> Tmp(getPtr()); |
309 | setPtr(nullptr); |
310 | setChecked(true); |
311 | return Tmp; |
312 | } |
313 | |
314 | friend raw_ostream &operator<<(raw_ostream &OS, const Error &E) { |
315 | if (auto *P = E.getPtr()) |
316 | P->log(OS); |
317 | else |
318 | OS << "success"; |
319 | return OS; |
320 | } |
321 | |
322 | ErrorInfoBase *Payload = nullptr; |
323 | }; |
324 | |
325 | /// Subclass of Error for the sole purpose of identifying the success path in |
326 | /// the type system. This allows to catch invalid conversion to Expected<T> at |
327 | /// compile time. |
328 | class ErrorSuccess final : public Error {}; |
329 | |
330 | inline ErrorSuccess Error::success() { return ErrorSuccess(); } |
331 | |
332 | /// Make a Error instance representing failure using the given error info |
333 | /// type. |
334 | template <typename ErrT, typename... ArgTs> Error make_error(ArgTs &&... Args) { |
335 | return Error(std::make_unique<ErrT>(std::forward<ArgTs>(Args)...)); |
336 | } |
337 | |
338 | /// Base class for user error types. Users should declare their error types |
339 | /// like: |
340 | /// |
341 | /// class MyError : public ErrorInfo<MyError> { |
342 | /// .... |
343 | /// }; |
344 | /// |
345 | /// This class provides an implementation of the ErrorInfoBase::kind |
346 | /// method, which is used by the Error RTTI system. |
347 | template <typename ThisErrT, typename ParentErrT = ErrorInfoBase> |
348 | class ErrorInfo : public ParentErrT { |
349 | public: |
350 | using ParentErrT::ParentErrT; // inherit constructors |
351 | |
352 | static const void *classID() { return &ThisErrT::ID; } |
353 | |
354 | const void *dynamicClassID() const override { return &ThisErrT::ID; } |
355 | |
356 | bool isA(const void *const ClassID) const override { |
357 | return ClassID == classID() || ParentErrT::isA(ClassID); |
358 | } |
359 | }; |
360 | |
361 | /// Special ErrorInfo subclass representing a list of ErrorInfos. |
362 | /// Instances of this class are constructed by joinError. |
363 | class ErrorList final : public ErrorInfo<ErrorList> { |
364 | // handleErrors needs to be able to iterate the payload list of an |
365 | // ErrorList. |
366 | template <typename... HandlerTs> |
367 | friend Error handleErrors(Error E, HandlerTs &&... Handlers); |
368 | |
369 | // joinErrors is implemented in terms of join. |
370 | friend Error joinErrors(Error, Error); |
371 | |
372 | public: |
373 | void log(raw_ostream &OS) const override { |
374 | OS << "Multiple errors:\n"; |
375 | for (const auto &ErrPayload : Payloads) { |
376 | ErrPayload->log(OS); |
377 | OS << "\n"; |
378 | } |
379 | } |
380 | |
381 | std::error_code convertToErrorCode() const override; |
382 | |
383 | // Used by ErrorInfo::classID. |
384 | static char ID; |
385 | |
386 | private: |
387 | ErrorList(std::unique_ptr<ErrorInfoBase> Payload1, |
388 | std::unique_ptr<ErrorInfoBase> Payload2) { |
389 | 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\"" , "llvm/include/llvm/Support/Error.h", 390, __extension__ __PRETTY_FUNCTION__ )) |
390 | "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\"" , "llvm/include/llvm/Support/Error.h", 390, __extension__ __PRETTY_FUNCTION__ )); |
391 | Payloads.push_back(std::move(Payload1)); |
392 | Payloads.push_back(std::move(Payload2)); |
393 | } |
394 | |
395 | static Error join(Error E1, Error E2) { |
396 | if (!E1) |
397 | return E2; |
398 | if (!E2) |
399 | return E1; |
400 | if (E1.isA<ErrorList>()) { |
401 | auto &E1List = static_cast<ErrorList &>(*E1.getPtr()); |
402 | if (E2.isA<ErrorList>()) { |
403 | auto E2Payload = E2.takePayload(); |
404 | auto &E2List = static_cast<ErrorList &>(*E2Payload); |
405 | for (auto &Payload : E2List.Payloads) |
406 | E1List.Payloads.push_back(std::move(Payload)); |
407 | } else |
408 | E1List.Payloads.push_back(E2.takePayload()); |
409 | |
410 | return E1; |
411 | } |
412 | if (E2.isA<ErrorList>()) { |
413 | auto &E2List = static_cast<ErrorList &>(*E2.getPtr()); |
414 | E2List.Payloads.insert(E2List.Payloads.begin(), E1.takePayload()); |
415 | return E2; |
416 | } |
417 | return Error(std::unique_ptr<ErrorList>( |
418 | new ErrorList(E1.takePayload(), E2.takePayload()))); |
419 | } |
420 | |
421 | std::vector<std::unique_ptr<ErrorInfoBase>> Payloads; |
422 | }; |
423 | |
424 | /// Concatenate errors. The resulting Error is unchecked, and contains the |
425 | /// ErrorInfo(s), if any, contained in E1, followed by the |
426 | /// ErrorInfo(s), if any, contained in E2. |
427 | inline Error joinErrors(Error E1, Error E2) { |
428 | return ErrorList::join(std::move(E1), std::move(E2)); |
429 | } |
430 | |
431 | /// Tagged union holding either a T or a Error. |
432 | /// |
433 | /// This class parallels ErrorOr, but replaces error_code with Error. Since |
434 | /// Error cannot be copied, this class replaces getError() with |
435 | /// takeError(). It also adds an bool errorIsA<ErrT>() method for testing the |
436 | /// error class type. |
437 | /// |
438 | /// Example usage of 'Expected<T>' as a function return type: |
439 | /// |
440 | /// @code{.cpp} |
441 | /// Expected<int> myDivide(int A, int B) { |
442 | /// if (B == 0) { |
443 | /// // return an Error |
444 | /// return createStringError(inconvertibleErrorCode(), |
445 | /// "B must not be zero!"); |
446 | /// } |
447 | /// // return an integer |
448 | /// return A / B; |
449 | /// } |
450 | /// @endcode |
451 | /// |
452 | /// Checking the results of to a function returning 'Expected<T>': |
453 | /// @code{.cpp} |
454 | /// if (auto E = Result.takeError()) { |
455 | /// // We must consume the error. Typically one of: |
456 | /// // - return the error to our caller |
457 | /// // - toString(), when logging |
458 | /// // - consumeError(), to silently swallow the error |
459 | /// // - handleErrors(), to distinguish error types |
460 | /// errs() << "Problem with division " << toString(std::move(E)) << "\n"; |
461 | /// return; |
462 | /// } |
463 | /// // use the result |
464 | /// outs() << "The answer is " << *Result << "\n"; |
465 | /// @endcode |
466 | /// |
467 | /// For unit-testing a function returning an 'Expected<T>', see the |
468 | /// 'EXPECT_THAT_EXPECTED' macros in llvm/Testing/Support/Error.h |
469 | |
470 | template <class T> class [[nodiscard]] Expected { |
471 | template <class T1> friend class ExpectedAsOutParameter; |
472 | template <class OtherT> friend class Expected; |
473 | |
474 | static constexpr bool isRef = std::is_reference_v<T>; |
475 | |
476 | using wrap = std::reference_wrapper<std::remove_reference_t<T>>; |
477 | |
478 | using error_type = std::unique_ptr<ErrorInfoBase>; |
479 | |
480 | public: |
481 | using storage_type = std::conditional_t<isRef, wrap, T>; |
482 | using value_type = T; |
483 | |
484 | private: |
485 | using reference = std::remove_reference_t<T> &; |
486 | using const_reference = const std::remove_reference_t<T> &; |
487 | using pointer = std::remove_reference_t<T> *; |
488 | using const_pointer = const std::remove_reference_t<T> *; |
489 | |
490 | public: |
491 | /// Create an Expected<T> error value from the given Error. |
492 | Expected(Error Err) |
493 | : HasError(true) |
494 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
495 | // Expected is unchecked upon construction in Debug builds. |
496 | , Unchecked(true) |
497 | #endif |
498 | { |
499 | 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.\"" , "llvm/include/llvm/Support/Error.h", 499, __extension__ __PRETTY_FUNCTION__ )); |
500 | new (getErrorStorage()) error_type(Err.takePayload()); |
501 | } |
502 | |
503 | /// Forbid to convert from Error::success() implicitly, this avoids having |
504 | /// Expected<T> foo() { return Error::success(); } which compiles otherwise |
505 | /// but triggers the assertion above. |
506 | Expected(ErrorSuccess) = delete; |
507 | |
508 | /// Create an Expected<T> success value from the given OtherT value, which |
509 | /// must be convertible to T. |
510 | template <typename OtherT> |
511 | Expected(OtherT &&Val, |
512 | std::enable_if_t<std::is_convertible_v<OtherT, T>> * = nullptr) |
513 | : HasError(false) |
514 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
515 | // Expected is unchecked upon construction in Debug builds. |
516 | , |
517 | Unchecked(true) |
518 | #endif |
519 | { |
520 | new (getStorage()) storage_type(std::forward<OtherT>(Val)); |
521 | } |
522 | |
523 | /// Move construct an Expected<T> value. |
524 | Expected(Expected &&Other) { moveConstruct(std::move(Other)); } |
525 | |
526 | /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT |
527 | /// must be convertible to T. |
528 | template <class OtherT> |
529 | Expected(Expected<OtherT> &&Other, |
530 | std::enable_if_t<std::is_convertible_v<OtherT, T>> * = nullptr) { |
531 | moveConstruct(std::move(Other)); |
532 | } |
533 | |
534 | /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT |
535 | /// isn't convertible to T. |
536 | template <class OtherT> |
537 | explicit Expected( |
538 | Expected<OtherT> &&Other, |
539 | std::enable_if_t<!std::is_convertible_v<OtherT, T>> * = nullptr) { |
540 | moveConstruct(std::move(Other)); |
541 | } |
542 | |
543 | /// Move-assign from another Expected<T>. |
544 | Expected &operator=(Expected &&Other) { |
545 | moveAssign(std::move(Other)); |
546 | return *this; |
547 | } |
548 | |
549 | /// Destroy an Expected<T>. |
550 | ~Expected() { |
551 | assertIsChecked(); |
552 | if (!HasError) |
553 | getStorage()->~storage_type(); |
554 | else |
555 | getErrorStorage()->~error_type(); |
556 | } |
557 | |
558 | /// Return false if there is an error. |
559 | explicit operator bool() { |
560 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
561 | Unchecked = HasError; |
562 | #endif |
563 | return !HasError; |
564 | } |
565 | |
566 | /// Returns a reference to the stored T value. |
567 | reference get() { |
568 | assertIsChecked(); |
569 | return *getStorage(); |
570 | } |
571 | |
572 | /// Returns a const reference to the stored T value. |
573 | const_reference get() const { |
574 | assertIsChecked(); |
575 | return const_cast<Expected<T> *>(this)->get(); |
576 | } |
577 | |
578 | /// Returns \a takeError() after moving the held T (if any) into \p V. |
579 | template <class OtherT> |
580 | Error moveInto( |
581 | OtherT &Value, |
582 | std::enable_if_t<std::is_assignable_v<OtherT &, T &&>> * = nullptr) && { |
583 | if (*this) |
584 | Value = std::move(get()); |
585 | return takeError(); |
586 | } |
587 | |
588 | /// Check that this Expected<T> is an error of type ErrT. |
589 | template <typename ErrT> bool errorIsA() const { |
590 | return HasError && (*getErrorStorage())->template isA<ErrT>(); |
591 | } |
592 | |
593 | /// Take ownership of the stored error. |
594 | /// After calling this the Expected<T> is in an indeterminate state that can |
595 | /// only be safely destructed. No further calls (beside the destructor) should |
596 | /// be made on the Expected<T> value. |
597 | Error takeError() { |
598 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
599 | Unchecked = false; |
600 | #endif |
601 | return HasError ? Error(std::move(*getErrorStorage())) : Error::success(); |
602 | } |
603 | |
604 | /// Returns a pointer to the stored T value. |
605 | pointer operator->() { |
606 | assertIsChecked(); |
607 | return toPointer(getStorage()); |
608 | } |
609 | |
610 | /// Returns a const pointer to the stored T value. |
611 | const_pointer operator->() const { |
612 | assertIsChecked(); |
613 | return toPointer(getStorage()); |
614 | } |
615 | |
616 | /// Returns a reference to the stored T value. |
617 | reference operator*() { |
618 | assertIsChecked(); |
619 | return *getStorage(); |
620 | } |
621 | |
622 | /// Returns a const reference to the stored T value. |
623 | const_reference operator*() const { |
624 | assertIsChecked(); |
625 | return *getStorage(); |
626 | } |
627 | |
628 | private: |
629 | template <class T1> |
630 | static bool compareThisIfSameType(const T1 &a, const T1 &b) { |
631 | return &a == &b; |
632 | } |
633 | |
634 | template <class T1, class T2> |
635 | static bool compareThisIfSameType(const T1 &, const T2 &) { |
636 | return false; |
637 | } |
638 | |
639 | template <class OtherT> void moveConstruct(Expected<OtherT> &&Other) { |
640 | HasError = Other.HasError; |
641 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
642 | Unchecked = true; |
643 | Other.Unchecked = false; |
644 | #endif |
645 | |
646 | if (!HasError) |
647 | new (getStorage()) storage_type(std::move(*Other.getStorage())); |
648 | else |
649 | new (getErrorStorage()) error_type(std::move(*Other.getErrorStorage())); |
650 | } |
651 | |
652 | template <class OtherT> void moveAssign(Expected<OtherT> &&Other) { |
653 | assertIsChecked(); |
654 | |
655 | if (compareThisIfSameType(*this, Other)) |
656 | return; |
657 | |
658 | this->~Expected(); |
659 | new (this) Expected(std::move(Other)); |
660 | } |
661 | |
662 | pointer toPointer(pointer Val) { return Val; } |
663 | |
664 | const_pointer toPointer(const_pointer Val) const { return Val; } |
665 | |
666 | pointer toPointer(wrap *Val) { return &Val->get(); } |
667 | |
668 | const_pointer toPointer(const wrap *Val) const { return &Val->get(); } |
669 | |
670 | storage_type *getStorage() { |
671 | 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!\"" , "llvm/include/llvm/Support/Error.h", 671, __extension__ __PRETTY_FUNCTION__ )); |
672 | return reinterpret_cast<storage_type *>(&TStorage); |
673 | } |
674 | |
675 | const storage_type *getStorage() const { |
676 | 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!\"" , "llvm/include/llvm/Support/Error.h", 676, __extension__ __PRETTY_FUNCTION__ )); |
677 | return reinterpret_cast<const storage_type *>(&TStorage); |
678 | } |
679 | |
680 | error_type *getErrorStorage() { |
681 | 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!\"" , "llvm/include/llvm/Support/Error.h", 681, __extension__ __PRETTY_FUNCTION__ )); |
682 | return reinterpret_cast<error_type *>(&ErrorStorage); |
683 | } |
684 | |
685 | const error_type *getErrorStorage() const { |
686 | 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!\"" , "llvm/include/llvm/Support/Error.h", 686, __extension__ __PRETTY_FUNCTION__ )); |
687 | return reinterpret_cast<const error_type *>(&ErrorStorage); |
688 | } |
689 | |
690 | // Used by ExpectedAsOutParameter to reset the checked flag. |
691 | void setUnchecked() { |
692 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
693 | Unchecked = true; |
694 | #endif |
695 | } |
696 | |
697 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
698 | [[noreturn]] LLVM_ATTRIBUTE_NOINLINE__attribute__((noinline)) void fatalUncheckedExpected() const { |
699 | dbgs() << "Expected<T> must be checked before access or destruction.\n"; |
700 | if (HasError) { |
701 | dbgs() << "Unchecked Expected<T> contained error:\n"; |
702 | (*getErrorStorage())->log(dbgs()); |
703 | } else |
704 | dbgs() << "Expected<T> value was in success state. (Note: Expected<T> " |
705 | "values in success mode must still be checked prior to being " |
706 | "destroyed).\n"; |
707 | abort(); |
708 | } |
709 | #endif |
710 | |
711 | void assertIsChecked() const { |
712 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
713 | if (LLVM_UNLIKELY(Unchecked)__builtin_expect((bool)(Unchecked), false)) |
714 | fatalUncheckedExpected(); |
715 | #endif |
716 | } |
717 | |
718 | union { |
719 | AlignedCharArrayUnion<storage_type> TStorage; |
720 | AlignedCharArrayUnion<error_type> ErrorStorage; |
721 | }; |
722 | bool HasError : 1; |
723 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
724 | bool Unchecked : 1; |
725 | #endif |
726 | }; |
727 | |
728 | /// Report a serious error, calling any installed error handler. See |
729 | /// ErrorHandling.h. |
730 | [[noreturn]] void report_fatal_error(Error Err, bool gen_crash_diag = true); |
731 | |
732 | /// Report a fatal error if Err is a failure value. |
733 | /// |
734 | /// This function can be used to wrap calls to fallible functions ONLY when it |
735 | /// is known that the Error will always be a success value. E.g. |
736 | /// |
737 | /// @code{.cpp} |
738 | /// // foo only attempts the fallible operation if DoFallibleOperation is |
739 | /// // true. If DoFallibleOperation is false then foo always returns |
740 | /// // Error::success(). |
741 | /// Error foo(bool DoFallibleOperation); |
742 | /// |
743 | /// cantFail(foo(false)); |
744 | /// @endcode |
745 | inline void cantFail(Error Err, const char *Msg = nullptr) { |
746 | if (Err) { |
747 | if (!Msg) |
748 | Msg = "Failure value returned from cantFail wrapped call"; |
749 | #ifndef NDEBUG |
750 | std::string Str; |
751 | raw_string_ostream OS(Str); |
752 | OS << Msg << "\n" << Err; |
753 | Msg = OS.str().c_str(); |
754 | #endif |
755 | llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "llvm/include/llvm/Support/Error.h" , 755); |
756 | } |
757 | } |
758 | |
759 | /// Report a fatal error if ValOrErr is a failure value, otherwise unwraps and |
760 | /// returns the contained value. |
761 | /// |
762 | /// This function can be used to wrap calls to fallible functions ONLY when it |
763 | /// is known that the Error will always be a success value. E.g. |
764 | /// |
765 | /// @code{.cpp} |
766 | /// // foo only attempts the fallible operation if DoFallibleOperation is |
767 | /// // true. If DoFallibleOperation is false then foo always returns an int. |
768 | /// Expected<int> foo(bool DoFallibleOperation); |
769 | /// |
770 | /// int X = cantFail(foo(false)); |
771 | /// @endcode |
772 | template <typename T> |
773 | T cantFail(Expected<T> ValOrErr, const char *Msg = nullptr) { |
774 | if (ValOrErr) |
775 | return std::move(*ValOrErr); |
776 | else { |
777 | if (!Msg) |
778 | Msg = "Failure value returned from cantFail wrapped call"; |
779 | #ifndef NDEBUG |
780 | std::string Str; |
781 | raw_string_ostream OS(Str); |
782 | auto E = ValOrErr.takeError(); |
783 | OS << Msg << "\n" << E; |
784 | Msg = OS.str().c_str(); |
785 | #endif |
786 | llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "llvm/include/llvm/Support/Error.h" , 786); |
787 | } |
788 | } |
789 | |
790 | /// Report a fatal error if ValOrErr is a failure value, otherwise unwraps and |
791 | /// returns the contained reference. |
792 | /// |
793 | /// This function can be used to wrap calls to fallible functions ONLY when it |
794 | /// is known that the Error will always be a success value. E.g. |
795 | /// |
796 | /// @code{.cpp} |
797 | /// // foo only attempts the fallible operation if DoFallibleOperation is |
798 | /// // true. If DoFallibleOperation is false then foo always returns a Bar&. |
799 | /// Expected<Bar&> foo(bool DoFallibleOperation); |
800 | /// |
801 | /// Bar &X = cantFail(foo(false)); |
802 | /// @endcode |
803 | template <typename T> |
804 | T& cantFail(Expected<T&> ValOrErr, const char *Msg = nullptr) { |
805 | if (ValOrErr) |
806 | return *ValOrErr; |
807 | else { |
808 | if (!Msg) |
809 | Msg = "Failure value returned from cantFail wrapped call"; |
810 | #ifndef NDEBUG |
811 | std::string Str; |
812 | raw_string_ostream OS(Str); |
813 | auto E = ValOrErr.takeError(); |
814 | OS << Msg << "\n" << E; |
815 | Msg = OS.str().c_str(); |
816 | #endif |
817 | llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "llvm/include/llvm/Support/Error.h" , 817); |
818 | } |
819 | } |
820 | |
821 | /// Helper for testing applicability of, and applying, handlers for |
822 | /// ErrorInfo types. |
823 | template <typename HandlerT> |
824 | class ErrorHandlerTraits |
825 | : public ErrorHandlerTraits< |
826 | decltype(&std::remove_reference_t<HandlerT>::operator())> {}; |
827 | |
828 | // Specialization functions of the form 'Error (const ErrT&)'. |
829 | template <typename ErrT> class ErrorHandlerTraits<Error (&)(ErrT &)> { |
830 | public: |
831 | static bool appliesTo(const ErrorInfoBase &E) { |
832 | return E.template isA<ErrT>(); |
833 | } |
834 | |
835 | template <typename HandlerT> |
836 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { |
837 | assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler" ) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "llvm/include/llvm/Support/Error.h", 837, __extension__ __PRETTY_FUNCTION__ )); |
838 | return H(static_cast<ErrT &>(*E)); |
839 | } |
840 | }; |
841 | |
842 | // Specialization functions of the form 'void (const ErrT&)'. |
843 | template <typename ErrT> class ErrorHandlerTraits<void (&)(ErrT &)> { |
844 | public: |
845 | static bool appliesTo(const ErrorInfoBase &E) { |
846 | return E.template isA<ErrT>(); |
847 | } |
848 | |
849 | template <typename HandlerT> |
850 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { |
851 | assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler" ) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "llvm/include/llvm/Support/Error.h", 851, __extension__ __PRETTY_FUNCTION__ )); |
852 | H(static_cast<ErrT &>(*E)); |
853 | return Error::success(); |
854 | } |
855 | }; |
856 | |
857 | /// Specialization for functions of the form 'Error (std::unique_ptr<ErrT>)'. |
858 | template <typename ErrT> |
859 | class ErrorHandlerTraits<Error (&)(std::unique_ptr<ErrT>)> { |
860 | public: |
861 | static bool appliesTo(const ErrorInfoBase &E) { |
862 | return E.template isA<ErrT>(); |
863 | } |
864 | |
865 | template <typename HandlerT> |
866 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { |
867 | assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler" ) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "llvm/include/llvm/Support/Error.h", 867, __extension__ __PRETTY_FUNCTION__ )); |
868 | std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release())); |
869 | return H(std::move(SubE)); |
870 | } |
871 | }; |
872 | |
873 | /// Specialization for functions of the form 'void (std::unique_ptr<ErrT>)'. |
874 | template <typename ErrT> |
875 | class ErrorHandlerTraits<void (&)(std::unique_ptr<ErrT>)> { |
876 | public: |
877 | static bool appliesTo(const ErrorInfoBase &E) { |
878 | return E.template isA<ErrT>(); |
879 | } |
880 | |
881 | template <typename HandlerT> |
882 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { |
883 | assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler" ) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "llvm/include/llvm/Support/Error.h", 883, __extension__ __PRETTY_FUNCTION__ )); |
884 | std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release())); |
885 | H(std::move(SubE)); |
886 | return Error::success(); |
887 | } |
888 | }; |
889 | |
890 | // Specialization for member functions of the form 'RetT (const ErrT&)'. |
891 | template <typename C, typename RetT, typename ErrT> |
892 | class ErrorHandlerTraits<RetT (C::*)(ErrT &)> |
893 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; |
894 | |
895 | // Specialization for member functions of the form 'RetT (const ErrT&) const'. |
896 | template <typename C, typename RetT, typename ErrT> |
897 | class ErrorHandlerTraits<RetT (C::*)(ErrT &) const> |
898 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; |
899 | |
900 | // Specialization for member functions of the form 'RetT (const ErrT&)'. |
901 | template <typename C, typename RetT, typename ErrT> |
902 | class ErrorHandlerTraits<RetT (C::*)(const ErrT &)> |
903 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; |
904 | |
905 | // Specialization for member functions of the form 'RetT (const ErrT&) const'. |
906 | template <typename C, typename RetT, typename ErrT> |
907 | class ErrorHandlerTraits<RetT (C::*)(const ErrT &) const> |
908 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; |
909 | |
910 | /// Specialization for member functions of the form |
911 | /// 'RetT (std::unique_ptr<ErrT>)'. |
912 | template <typename C, typename RetT, typename ErrT> |
913 | class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>)> |
914 | : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {}; |
915 | |
916 | /// Specialization for member functions of the form |
917 | /// 'RetT (std::unique_ptr<ErrT>) const'. |
918 | template <typename C, typename RetT, typename ErrT> |
919 | class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>) const> |
920 | : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {}; |
921 | |
922 | inline Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload) { |
923 | return Error(std::move(Payload)); |
924 | } |
925 | |
926 | template <typename HandlerT, typename... HandlerTs> |
927 | Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload, |
928 | HandlerT &&Handler, HandlerTs &&... Handlers) { |
929 | if (ErrorHandlerTraits<HandlerT>::appliesTo(*Payload)) |
930 | return ErrorHandlerTraits<HandlerT>::apply(std::forward<HandlerT>(Handler), |
931 | std::move(Payload)); |
932 | return handleErrorImpl(std::move(Payload), |
933 | std::forward<HandlerTs>(Handlers)...); |
934 | } |
935 | |
936 | /// Pass the ErrorInfo(s) contained in E to their respective handlers. Any |
937 | /// unhandled errors (or Errors returned by handlers) are re-concatenated and |
938 | /// returned. |
939 | /// Because this function returns an error, its result must also be checked |
940 | /// or returned. If you intend to handle all errors use handleAllErrors |
941 | /// (which returns void, and will abort() on unhandled errors) instead. |
942 | template <typename... HandlerTs> |
943 | Error handleErrors(Error E, HandlerTs &&... Hs) { |
944 | if (!E) |
945 | return Error::success(); |
946 | |
947 | std::unique_ptr<ErrorInfoBase> Payload = E.takePayload(); |
948 | |
949 | if (Payload->isA<ErrorList>()) { |
950 | ErrorList &List = static_cast<ErrorList &>(*Payload); |
951 | Error R; |
952 | for (auto &P : List.Payloads) |
953 | R = ErrorList::join( |
954 | std::move(R), |
955 | handleErrorImpl(std::move(P), std::forward<HandlerTs>(Hs)...)); |
956 | return R; |
957 | } |
958 | |
959 | return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...); |
960 | } |
961 | |
962 | /// Behaves the same as handleErrors, except that by contract all errors |
963 | /// *must* be handled by the given handlers (i.e. there must be no remaining |
964 | /// errors after running the handlers, or llvm_unreachable is called). |
965 | template <typename... HandlerTs> |
966 | void handleAllErrors(Error E, HandlerTs &&... Handlers) { |
967 | cantFail(handleErrors(std::move(E), std::forward<HandlerTs>(Handlers)...)); |
968 | } |
969 | |
970 | /// Check that E is a non-error, then drop it. |
971 | /// If E is an error, llvm_unreachable will be called. |
972 | inline void handleAllErrors(Error E) { |
973 | cantFail(std::move(E)); |
974 | } |
975 | |
976 | /// Handle any errors (if present) in an Expected<T>, then try a recovery path. |
977 | /// |
978 | /// If the incoming value is a success value it is returned unmodified. If it |
979 | /// is a failure value then it the contained error is passed to handleErrors. |
980 | /// If handleErrors is able to handle the error then the RecoveryPath functor |
981 | /// is called to supply the final result. If handleErrors is not able to |
982 | /// handle all errors then the unhandled errors are returned. |
983 | /// |
984 | /// This utility enables the follow pattern: |
985 | /// |
986 | /// @code{.cpp} |
987 | /// enum FooStrategy { Aggressive, Conservative }; |
988 | /// Expected<Foo> foo(FooStrategy S); |
989 | /// |
990 | /// auto ResultOrErr = |
991 | /// handleExpected( |
992 | /// foo(Aggressive), |
993 | /// []() { return foo(Conservative); }, |
994 | /// [](AggressiveStrategyError&) { |
995 | /// // Implicitly conusme this - we'll recover by using a conservative |
996 | /// // strategy. |
997 | /// }); |
998 | /// |
999 | /// @endcode |
1000 | template <typename T, typename RecoveryFtor, typename... HandlerTs> |
1001 | Expected<T> handleExpected(Expected<T> ValOrErr, RecoveryFtor &&RecoveryPath, |
1002 | HandlerTs &&... Handlers) { |
1003 | if (ValOrErr) |
1004 | return ValOrErr; |
1005 | |
1006 | if (auto Err = handleErrors(ValOrErr.takeError(), |
1007 | std::forward<HandlerTs>(Handlers)...)) |
1008 | return std::move(Err); |
1009 | |
1010 | return RecoveryPath(); |
1011 | } |
1012 | |
1013 | /// Log all errors (if any) in E to OS. If there are any errors, ErrorBanner |
1014 | /// will be printed before the first one is logged. A newline will be printed |
1015 | /// after each error. |
1016 | /// |
1017 | /// This function is compatible with the helpers from Support/WithColor.h. You |
1018 | /// can pass any of them as the OS. Please consider using them instead of |
1019 | /// including 'error: ' in the ErrorBanner. |
1020 | /// |
1021 | /// This is useful in the base level of your program to allow clean termination |
1022 | /// (allowing clean deallocation of resources, etc.), while reporting error |
1023 | /// information to the user. |
1024 | void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner = {}); |
1025 | |
1026 | /// Write all error messages (if any) in E to a string. The newline character |
1027 | /// is used to separate error messages. |
1028 | inline std::string toString(Error E) { |
1029 | SmallVector<std::string, 2> Errors; |
1030 | handleAllErrors(std::move(E), [&Errors](const ErrorInfoBase &EI) { |
1031 | Errors.push_back(EI.message()); |
1032 | }); |
1033 | return join(Errors.begin(), Errors.end(), "\n"); |
1034 | } |
1035 | |
1036 | /// Consume a Error without doing anything. This method should be used |
1037 | /// only where an error can be considered a reasonable and expected return |
1038 | /// value. |
1039 | /// |
1040 | /// Uses of this method are potentially indicative of design problems: If it's |
1041 | /// legitimate to do nothing while processing an "error", the error-producer |
1042 | /// might be more clearly refactored to return an std::optional<T>. |
1043 | inline void consumeError(Error Err) { |
1044 | handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {}); |
1045 | } |
1046 | |
1047 | /// Convert an Expected to an Optional without doing anything. This method |
1048 | /// should be used only where an error can be considered a reasonable and |
1049 | /// expected return value. |
1050 | /// |
1051 | /// Uses of this method are potentially indicative of problems: perhaps the |
1052 | /// error should be propagated further, or the error-producer should just |
1053 | /// return an Optional in the first place. |
1054 | template <typename T> std::optional<T> expectedToOptional(Expected<T> &&E) { |
1055 | if (E) |
1056 | return std::move(*E); |
1057 | consumeError(E.takeError()); |
1058 | return std::nullopt; |
1059 | } |
1060 | |
1061 | template <typename T> std::optional<T> expectedToStdOptional(Expected<T> &&E) { |
1062 | if (E) |
1063 | return std::move(*E); |
1064 | consumeError(E.takeError()); |
1065 | return std::nullopt; |
1066 | } |
1067 | |
1068 | /// Helper for converting an Error to a bool. |
1069 | /// |
1070 | /// This method returns true if Err is in an error state, or false if it is |
1071 | /// in a success state. Puts Err in a checked state in both cases (unlike |
1072 | /// Error::operator bool(), which only does this for success states). |
1073 | inline bool errorToBool(Error Err) { |
1074 | bool IsError = static_cast<bool>(Err); |
1075 | if (IsError) |
1076 | consumeError(std::move(Err)); |
1077 | return IsError; |
1078 | } |
1079 | |
1080 | /// Helper for Errors used as out-parameters. |
1081 | /// |
1082 | /// This helper is for use with the Error-as-out-parameter idiom, where an error |
1083 | /// is passed to a function or method by reference, rather than being returned. |
1084 | /// In such cases it is helpful to set the checked bit on entry to the function |
1085 | /// so that the error can be written to (unchecked Errors abort on assignment) |
1086 | /// and clear the checked bit on exit so that clients cannot accidentally forget |
1087 | /// to check the result. This helper performs these actions automatically using |
1088 | /// RAII: |
1089 | /// |
1090 | /// @code{.cpp} |
1091 | /// Result foo(Error &Err) { |
1092 | /// ErrorAsOutParameter ErrAsOutParam(&Err); // 'Checked' flag set |
1093 | /// // <body of foo> |
1094 | /// // <- 'Checked' flag auto-cleared when ErrAsOutParam is destructed. |
1095 | /// } |
1096 | /// @endcode |
1097 | /// |
1098 | /// ErrorAsOutParameter takes an Error* rather than Error& so that it can be |
1099 | /// used with optional Errors (Error pointers that are allowed to be null). If |
1100 | /// ErrorAsOutParameter took an Error reference, an instance would have to be |
1101 | /// created inside every condition that verified that Error was non-null. By |
1102 | /// taking an Error pointer we can just create one instance at the top of the |
1103 | /// function. |
1104 | class ErrorAsOutParameter { |
1105 | public: |
1106 | ErrorAsOutParameter(Error *Err) : Err(Err) { |
1107 | // Raise the checked bit if Err is success. |
1108 | if (Err) |
1109 | (void)!!*Err; |
1110 | } |
1111 | |
1112 | ~ErrorAsOutParameter() { |
1113 | // Clear the checked bit. |
1114 | if (Err && !*Err) |
1115 | *Err = Error::success(); |
1116 | } |
1117 | |
1118 | private: |
1119 | Error *Err; |
1120 | }; |
1121 | |
1122 | /// Helper for Expected<T>s used as out-parameters. |
1123 | /// |
1124 | /// See ErrorAsOutParameter. |
1125 | template <typename T> |
1126 | class ExpectedAsOutParameter { |
1127 | public: |
1128 | ExpectedAsOutParameter(Expected<T> *ValOrErr) |
1129 | : ValOrErr(ValOrErr) { |
1130 | if (ValOrErr) |
1131 | (void)!!*ValOrErr; |
1132 | } |
1133 | |
1134 | ~ExpectedAsOutParameter() { |
1135 | if (ValOrErr) |
1136 | ValOrErr->setUnchecked(); |
1137 | } |
1138 | |
1139 | private: |
1140 | Expected<T> *ValOrErr; |
1141 | }; |
1142 | |
1143 | /// This class wraps a std::error_code in a Error. |
1144 | /// |
1145 | /// This is useful if you're writing an interface that returns a Error |
1146 | /// (or Expected) and you want to call code that still returns |
1147 | /// std::error_codes. |
1148 | class ECError : public ErrorInfo<ECError> { |
1149 | friend Error errorCodeToError(std::error_code); |
1150 | |
1151 | void anchor() override; |
1152 | |
1153 | public: |
1154 | void setErrorCode(std::error_code EC) { this->EC = EC; } |
1155 | std::error_code convertToErrorCode() const override { return EC; } |
1156 | void log(raw_ostream &OS) const override { OS << EC.message(); } |
1157 | |
1158 | // Used by ErrorInfo::classID. |
1159 | static char ID; |
1160 | |
1161 | protected: |
1162 | ECError() = default; |
1163 | ECError(std::error_code EC) : EC(EC) {} |
1164 | |
1165 | std::error_code EC; |
1166 | }; |
1167 | |
1168 | /// The value returned by this function can be returned from convertToErrorCode |
1169 | /// for Error values where no sensible translation to std::error_code exists. |
1170 | /// It should only be used in this situation, and should never be used where a |
1171 | /// sensible conversion to std::error_code is available, as attempts to convert |
1172 | /// to/from this error will result in a fatal error. (i.e. it is a programmatic |
1173 | /// error to try to convert such a value). |
1174 | std::error_code inconvertibleErrorCode(); |
1175 | |
1176 | /// Helper for converting an std::error_code to a Error. |
1177 | Error errorCodeToError(std::error_code EC); |
1178 | |
1179 | /// Helper for converting an ECError to a std::error_code. |
1180 | /// |
1181 | /// This method requires that Err be Error() or an ECError, otherwise it |
1182 | /// will trigger a call to abort(). |
1183 | std::error_code errorToErrorCode(Error Err); |
1184 | |
1185 | /// Convert an ErrorOr<T> to an Expected<T>. |
1186 | template <typename T> Expected<T> errorOrToExpected(ErrorOr<T> &&EO) { |
1187 | if (auto EC = EO.getError()) |
1188 | return errorCodeToError(EC); |
1189 | return std::move(*EO); |
1190 | } |
1191 | |
1192 | /// Convert an Expected<T> to an ErrorOr<T>. |
1193 | template <typename T> ErrorOr<T> expectedToErrorOr(Expected<T> &&E) { |
1194 | if (auto Err = E.takeError()) |
1195 | return errorToErrorCode(std::move(Err)); |
1196 | return std::move(*E); |
1197 | } |
1198 | |
1199 | /// This class wraps a string in an Error. |
1200 | /// |
1201 | /// StringError is useful in cases where the client is not expected to be able |
1202 | /// to consume the specific error message programmatically (for example, if the |
1203 | /// error message is to be presented to the user). |
1204 | /// |
1205 | /// StringError can also be used when additional information is to be printed |
1206 | /// along with a error_code message. Depending on the constructor called, this |
1207 | /// class can either display: |
1208 | /// 1. the error_code message (ECError behavior) |
1209 | /// 2. a string |
1210 | /// 3. the error_code message and a string |
1211 | /// |
1212 | /// These behaviors are useful when subtyping is required; for example, when a |
1213 | /// specific library needs an explicit error type. In the example below, |
1214 | /// PDBError is derived from StringError: |
1215 | /// |
1216 | /// @code{.cpp} |
1217 | /// Expected<int> foo() { |
1218 | /// return llvm::make_error<PDBError>(pdb_error_code::dia_failed_loading, |
1219 | /// "Additional information"); |
1220 | /// } |
1221 | /// @endcode |
1222 | /// |
1223 | class StringError : public ErrorInfo<StringError> { |
1224 | public: |
1225 | static char ID; |
1226 | |
1227 | // Prints EC + S and converts to EC |
1228 | StringError(std::error_code EC, const Twine &S = Twine()); |
1229 | |
1230 | // Prints S and converts to EC |
1231 | StringError(const Twine &S, std::error_code EC); |
1232 | |
1233 | void log(raw_ostream &OS) const override; |
1234 | std::error_code convertToErrorCode() const override; |
1235 | |
1236 | const std::string &getMessage() const { return Msg; } |
1237 | |
1238 | private: |
1239 | std::string Msg; |
1240 | std::error_code EC; |
1241 | const bool PrintMsgOnly = false; |
1242 | }; |
1243 | |
1244 | /// Create formatted StringError object. |
1245 | template <typename... Ts> |
1246 | inline Error createStringError(std::error_code EC, char const *Fmt, |
1247 | const Ts &... Vals) { |
1248 | std::string Buffer; |
1249 | raw_string_ostream Stream(Buffer); |
1250 | Stream << format(Fmt, Vals...); |
1251 | return make_error<StringError>(Stream.str(), EC); |
1252 | } |
1253 | |
1254 | Error createStringError(std::error_code EC, char const *Msg); |
1255 | |
1256 | inline Error createStringError(std::error_code EC, const Twine &S) { |
1257 | return createStringError(EC, S.str().c_str()); |
1258 | } |
1259 | |
1260 | template <typename... Ts> |
1261 | inline Error createStringError(std::errc EC, char const *Fmt, |
1262 | const Ts &... Vals) { |
1263 | return createStringError(std::make_error_code(EC), Fmt, Vals...); |
1264 | } |
1265 | |
1266 | /// This class wraps a filename and another Error. |
1267 | /// |
1268 | /// In some cases, an error needs to live along a 'source' name, in order to |
1269 | /// show more detailed information to the user. |
1270 | class FileError final : public ErrorInfo<FileError> { |
1271 | |
1272 | friend Error createFileError(const Twine &, Error); |
1273 | friend Error createFileError(const Twine &, size_t, Error); |
1274 | |
1275 | public: |
1276 | void log(raw_ostream &OS) const override { |
1277 | assert(Err && "Trying to log after takeError().")(static_cast <bool> (Err && "Trying to log after takeError()." ) ? void (0) : __assert_fail ("Err && \"Trying to log after takeError().\"" , "llvm/include/llvm/Support/Error.h", 1277, __extension__ __PRETTY_FUNCTION__ )); |
1278 | OS << "'" << FileName << "': "; |
1279 | if (Line) |
1280 | OS << "line " << *Line << ": "; |
1281 | Err->log(OS); |
1282 | } |
1283 | |
1284 | std::string messageWithoutFileInfo() const { |
1285 | std::string Msg; |
1286 | raw_string_ostream OS(Msg); |
1287 | Err->log(OS); |
1288 | return OS.str(); |
1289 | } |
1290 | |
1291 | StringRef getFileName() const { return FileName; } |
1292 | |
1293 | Error takeError() { return Error(std::move(Err)); } |
1294 | |
1295 | std::error_code convertToErrorCode() const override; |
1296 | |
1297 | // Used by ErrorInfo::classID. |
1298 | static char ID; |
1299 | |
1300 | private: |
1301 | FileError(const Twine &F, std::optional<size_t> LineNum, |
1302 | std::unique_ptr<ErrorInfoBase> E) { |
1303 | assert(E && "Cannot create FileError from Error success value.")(static_cast <bool> (E && "Cannot create FileError from Error success value." ) ? void (0) : __assert_fail ("E && \"Cannot create FileError from Error success value.\"" , "llvm/include/llvm/Support/Error.h", 1303, __extension__ __PRETTY_FUNCTION__ )); |
1304 | FileName = F.str(); |
1305 | Err = std::move(E); |
1306 | Line = std::move(LineNum); |
1307 | } |
1308 | |
1309 | static Error build(const Twine &F, std::optional<size_t> Line, Error E) { |
1310 | std::unique_ptr<ErrorInfoBase> Payload; |
1311 | handleAllErrors(std::move(E), |
1312 | [&](std::unique_ptr<ErrorInfoBase> EIB) -> Error { |
1313 | Payload = std::move(EIB); |
1314 | return Error::success(); |
1315 | }); |
1316 | return Error( |
1317 | std::unique_ptr<FileError>(new FileError(F, Line, std::move(Payload)))); |
1318 | } |
1319 | |
1320 | std::string FileName; |
1321 | std::optional<size_t> Line; |
1322 | std::unique_ptr<ErrorInfoBase> Err; |
1323 | }; |
1324 | |
1325 | /// Concatenate a source file path and/or name with an Error. The resulting |
1326 | /// Error is unchecked. |
1327 | inline Error createFileError(const Twine &F, Error E) { |
1328 | return FileError::build(F, std::optional<size_t>(), std::move(E)); |
1329 | } |
1330 | |
1331 | /// Concatenate a source file path and/or name with line number and an Error. |
1332 | /// The resulting Error is unchecked. |
1333 | inline Error createFileError(const Twine &F, size_t Line, Error E) { |
1334 | return FileError::build(F, std::optional<size_t>(Line), std::move(E)); |
1335 | } |
1336 | |
1337 | /// Concatenate a source file path and/or name with a std::error_code |
1338 | /// to form an Error object. |
1339 | inline Error createFileError(const Twine &F, std::error_code EC) { |
1340 | return createFileError(F, errorCodeToError(EC)); |
1341 | } |
1342 | |
1343 | /// Concatenate a source file path and/or name with line number and |
1344 | /// std::error_code to form an Error object. |
1345 | inline Error createFileError(const Twine &F, size_t Line, std::error_code EC) { |
1346 | return createFileError(F, Line, errorCodeToError(EC)); |
1347 | } |
1348 | |
1349 | Error createFileError(const Twine &F, ErrorSuccess) = delete; |
1350 | |
1351 | /// Helper for check-and-exit error handling. |
1352 | /// |
1353 | /// For tool use only. NOT FOR USE IN LIBRARY CODE. |
1354 | /// |
1355 | class ExitOnError { |
1356 | public: |
1357 | /// Create an error on exit helper. |
1358 | ExitOnError(std::string Banner = "", int DefaultErrorExitCode = 1) |
1359 | : Banner(std::move(Banner)), |
1360 | GetExitCode([=](const Error &) { return DefaultErrorExitCode; }) {} |
1361 | |
1362 | /// Set the banner string for any errors caught by operator(). |
1363 | void setBanner(std::string Banner) { this->Banner = std::move(Banner); } |
1364 | |
1365 | /// Set the exit-code mapper function. |
1366 | void setExitCodeMapper(std::function<int(const Error &)> GetExitCode) { |
1367 | this->GetExitCode = std::move(GetExitCode); |
1368 | } |
1369 | |
1370 | /// Check Err. If it's in a failure state log the error(s) and exit. |
1371 | void operator()(Error Err) const { checkError(std::move(Err)); } |
1372 | |
1373 | /// Check E. If it's in a success state then return the contained value. If |
1374 | /// it's in a failure state log the error(s) and exit. |
1375 | template <typename T> T operator()(Expected<T> &&E) const { |
1376 | checkError(E.takeError()); |
1377 | return std::move(*E); |
1378 | } |
1379 | |
1380 | /// Check E. If it's in a success state then return the contained reference. If |
1381 | /// it's in a failure state log the error(s) and exit. |
1382 | template <typename T> T& operator()(Expected<T&> &&E) const { |
1383 | checkError(E.takeError()); |
1384 | return *E; |
1385 | } |
1386 | |
1387 | private: |
1388 | void checkError(Error Err) const { |
1389 | if (Err) { |
1390 | int ExitCode = GetExitCode(Err); |
1391 | logAllUnhandledErrors(std::move(Err), errs(), Banner); |
1392 | exit(ExitCode); |
1393 | } |
1394 | } |
1395 | |
1396 | std::string Banner; |
1397 | std::function<int(const Error &)> GetExitCode; |
1398 | }; |
1399 | |
1400 | /// Conversion from Error to LLVMErrorRef for C error bindings. |
1401 | inline LLVMErrorRef wrap(Error Err) { |
1402 | return reinterpret_cast<LLVMErrorRef>(Err.takePayload().release()); |
1403 | } |
1404 | |
1405 | /// Conversion from LLVMErrorRef to Error for C error bindings. |
1406 | inline Error unwrap(LLVMErrorRef ErrRef) { |
1407 | return Error(std::unique_ptr<ErrorInfoBase>( |
1408 | reinterpret_cast<ErrorInfoBase *>(ErrRef))); |
1409 | } |
1410 | |
1411 | } // end namespace llvm |
1412 | |
1413 | #endif // LLVM_SUPPORT_ERROR_H |