]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
Merge lld trunk r321017 to contrib/llvm/tools/lld.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lld / lib / ReaderWriter / YAML / ReaderWriterYAML.cpp
1 //===- lib/ReaderWriter/YAML/ReaderWriterYAML.cpp -------------------------===//
2 //
3 //                             The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lld/Core/AbsoluteAtom.h"
11 #include "lld/Core/ArchiveLibraryFile.h"
12 #include "lld/Core/Atom.h"
13 #include "lld/Core/DefinedAtom.h"
14 #include "lld/Core/Error.h"
15 #include "lld/Core/File.h"
16 #include "lld/Core/LinkingContext.h"
17 #include "lld/Core/Reader.h"
18 #include "lld/Core/Reference.h"
19 #include "lld/Core/SharedLibraryAtom.h"
20 #include "lld/Core/Simple.h"
21 #include "lld/Core/UndefinedAtom.h"
22 #include "lld/Core/Writer.h"
23 #include "lld/ReaderWriter/YamlContext.h"
24 #include "llvm/ADT/ArrayRef.h"
25 #include "llvm/ADT/DenseMap.h"
26 #include "llvm/ADT/StringMap.h"
27 #include "llvm/ADT/StringRef.h"
28 #include "llvm/ADT/Twine.h"
29 #include "llvm/BinaryFormat/Magic.h"
30 #include "llvm/Support/Allocator.h"
31 #include "llvm/Support/Debug.h"
32 #include "llvm/Support/Error.h"
33 #include "llvm/Support/ErrorOr.h"
34 #include "llvm/Support/FileSystem.h"
35 #include "llvm/Support/Format.h"
36 #include "llvm/Support/MemoryBuffer.h"
37 #include "llvm/Support/YAMLTraits.h"
38 #include "llvm/Support/raw_ostream.h"
39 #include <cassert>
40 #include <cstdint>
41 #include <cstring>
42 #include <memory>
43 #include <string>
44 #include <system_error>
45 #include <vector>
46
47 using llvm::file_magic;
48 using llvm::yaml::MappingTraits;
49 using llvm::yaml::ScalarEnumerationTraits;
50 using llvm::yaml::ScalarTraits;
51 using llvm::yaml::IO;
52 using llvm::yaml::SequenceTraits;
53 using llvm::yaml::DocumentListTraits;
54
55 using namespace lld;
56
57 /// The conversion of Atoms to and from YAML uses LLVM's YAML I/O.  This
58 /// file just defines template specializations on the lld types which control
59 /// how the mapping is done to and from YAML.
60
61 namespace {
62
63 /// Used when writing yaml files.
64 /// In most cases, atoms names are unambiguous, so references can just
65 /// use the atom name as the target (e.g. target: foo).  But in a few
66 /// cases that does not work, so ref-names are added.  These are labels
67 /// used only in yaml.  The labels do not exist in the Atom model.
68 ///
69 /// One need for ref-names are when atoms have no user supplied name
70 /// (e.g. c-string literal).  Another case is when two object files with
71 /// identically named static functions are merged (ld -r) into one object file.
72 /// In that case referencing the function by name is ambiguous, so a unique
73 /// ref-name is added.
74 class RefNameBuilder {
75 public:
76   RefNameBuilder(const lld::File &file)
77       : _collisionCount(0), _unnamedCounter(0) {
78     // visit all atoms
79     for (const lld::DefinedAtom *atom : file.defined()) {
80       // Build map of atoms names to detect duplicates
81       if (!atom->name().empty())
82         buildDuplicateNameMap(*atom);
83
84       // Find references to unnamed atoms and create ref-names for them.
85       for (const lld::Reference *ref : *atom) {
86         // create refname for any unnamed reference target
87         const lld::Atom *target = ref->target();
88         if ((target != nullptr) && target->name().empty()) {
89           std::string storage;
90           llvm::raw_string_ostream buffer(storage);
91           buffer << llvm::format("L%03d", _unnamedCounter++);
92           StringRef newName = copyString(buffer.str());
93           _refNames[target] = newName;
94           DEBUG_WITH_TYPE("WriterYAML",
95                           llvm::dbgs() << "unnamed atom: creating ref-name: '"
96                                        << newName << "' ("
97                                        << (const void *)newName.data() << ", "
98                                        << newName.size() << ")\n");
99         }
100       }
101     }
102     for (const lld::UndefinedAtom *undefAtom : file.undefined()) {
103       buildDuplicateNameMap(*undefAtom);
104     }
105     for (const lld::SharedLibraryAtom *shlibAtom : file.sharedLibrary()) {
106       buildDuplicateNameMap(*shlibAtom);
107     }
108     for (const lld::AbsoluteAtom *absAtom : file.absolute()) {
109       if (!absAtom->name().empty())
110         buildDuplicateNameMap(*absAtom);
111     }
112   }
113
114   void buildDuplicateNameMap(const lld::Atom &atom) {
115     assert(!atom.name().empty());
116     NameToAtom::iterator pos = _nameMap.find(atom.name());
117     if (pos != _nameMap.end()) {
118       // Found name collision, give each a unique ref-name.
119       std::string Storage;
120       llvm::raw_string_ostream buffer(Storage);
121       buffer << atom.name() << llvm::format(".%03d", ++_collisionCount);
122       StringRef newName = copyString(buffer.str());
123       _refNames[&atom] = newName;
124       DEBUG_WITH_TYPE("WriterYAML",
125                       llvm::dbgs() << "name collsion: creating ref-name: '"
126                                    << newName << "' ("
127                                    << (const void *)newName.data()
128                                    << ", " << newName.size() << ")\n");
129       const lld::Atom *prevAtom = pos->second;
130       AtomToRefName::iterator pos2 = _refNames.find(prevAtom);
131       if (pos2 == _refNames.end()) {
132         // Only create ref-name for previous if none already created.
133         std::string Storage2;
134         llvm::raw_string_ostream buffer2(Storage2);
135         buffer2 << prevAtom->name() << llvm::format(".%03d", ++_collisionCount);
136         StringRef newName2 = copyString(buffer2.str());
137         _refNames[prevAtom] = newName2;
138         DEBUG_WITH_TYPE("WriterYAML",
139                         llvm::dbgs() << "name collsion: creating ref-name: '"
140                                      << newName2 << "' ("
141                                      << (const void *)newName2.data() << ", "
142                                      << newName2.size() << ")\n");
143       }
144     } else {
145       // First time we've seen this name, just add it to map.
146       _nameMap[atom.name()] = &atom;
147       DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs()
148                                         << "atom name seen for first time: '"
149                                         << atom.name() << "' ("
150                                         << (const void *)atom.name().data()
151                                         << ", " << atom.name().size() << ")\n");
152     }
153   }
154
155   bool hasRefName(const lld::Atom *atom) { return _refNames.count(atom); }
156
157   StringRef refName(const lld::Atom *atom) {
158     return _refNames.find(atom)->second;
159   }
160
161 private:
162   typedef llvm::StringMap<const lld::Atom *> NameToAtom;
163   typedef llvm::DenseMap<const lld::Atom *, std::string> AtomToRefName;
164
165   // Allocate a new copy of this string in _storage, so the strings
166   // can be freed when RefNameBuilder is destroyed.
167   StringRef copyString(StringRef str) {
168     char *s = _storage.Allocate<char>(str.size());
169     memcpy(s, str.data(), str.size());
170     return StringRef(s, str.size());
171   }
172
173   unsigned int                         _collisionCount;
174   unsigned int                         _unnamedCounter;
175   NameToAtom                           _nameMap;
176   AtomToRefName                        _refNames;
177   llvm::BumpPtrAllocator               _storage;
178 };
179
180 /// Used when reading yaml files to find the target of a reference
181 /// that could be a name or ref-name.
182 class RefNameResolver {
183 public:
184   RefNameResolver(const lld::File *file, IO &io);
185
186   const lld::Atom *lookup(StringRef name) const {
187     NameToAtom::const_iterator pos = _nameMap.find(name);
188     if (pos != _nameMap.end())
189       return pos->second;
190     _io.setError(Twine("no such atom name: ") + name);
191     return nullptr;
192   }
193
194 private:
195   typedef llvm::StringMap<const lld::Atom *> NameToAtom;
196
197   void add(StringRef name, const lld::Atom *atom) {
198     if (_nameMap.count(name)) {
199       _io.setError(Twine("duplicate atom name: ") + name);
200     } else {
201       _nameMap[name] = atom;
202     }
203   }
204
205   IO &_io;
206   NameToAtom _nameMap;
207 };
208
209 /// Mapping of Atoms.
210 template <typename T> class AtomList {
211   using Ty = std::vector<OwningAtomPtr<T>>;
212
213 public:
214   typename Ty::iterator begin() { return _atoms.begin(); }
215   typename Ty::iterator end() { return _atoms.end(); }
216   Ty _atoms;
217 };
218
219 /// Mapping of kind: field in yaml files.
220 enum FileKinds {
221   fileKindObjectAtoms, // atom based object file encoded in yaml
222   fileKindArchive,     // static archive library encoded in yaml
223   fileKindObjectMachO  // mach-o object files encoded in yaml
224 };
225
226 struct ArchMember {
227   FileKinds         _kind;
228   StringRef         _name;
229   const lld::File  *_content;
230 };
231
232 // The content bytes in a DefinedAtom are just uint8_t but we want
233 // special formatting, so define a strong type.
234 LLVM_YAML_STRONG_TYPEDEF(uint8_t, ImplicitHex8)
235
236 // SharedLibraryAtoms have a bool canBeNull() method which we'd like to be
237 // more readable than just true/false.
238 LLVM_YAML_STRONG_TYPEDEF(bool, ShlibCanBeNull)
239
240 // lld::Reference::Kind is a tuple of <namespace, arch, value>.
241 // For yaml, we just want one string that encapsulates the tuple.
242 struct RefKind {
243   Reference::KindNamespace  ns;
244   Reference::KindArch       arch;
245   Reference::KindValue      value;
246 };
247
248 } // end anonymous namespace
249
250 LLVM_YAML_IS_SEQUENCE_VECTOR(ArchMember)
251 LLVM_YAML_IS_SEQUENCE_VECTOR(const lld::Reference *)
252 // Always write DefinedAtoms content bytes as a flow sequence.
253 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(ImplicitHex8)
254
255 // for compatibility with gcc-4.7 in C++11 mode, add extra namespace
256 namespace llvm {
257 namespace yaml {
258
259 // This is a custom formatter for RefKind
260 template <> struct ScalarTraits<RefKind> {
261   static void output(const RefKind &kind, void *ctxt, raw_ostream &out) {
262     assert(ctxt != nullptr);
263     YamlContext *info = reinterpret_cast<YamlContext *>(ctxt);
264     assert(info->_registry);
265     StringRef str;
266     if (info->_registry->referenceKindToString(kind.ns, kind.arch, kind.value,
267                                                str))
268       out << str;
269     else
270       out << (int)(kind.ns) << "-" << (int)(kind.arch) << "-" << kind.value;
271   }
272
273   static StringRef input(StringRef scalar, void *ctxt, RefKind &kind) {
274     assert(ctxt != nullptr);
275     YamlContext *info = reinterpret_cast<YamlContext *>(ctxt);
276     assert(info->_registry);
277     if (info->_registry->referenceKindFromString(scalar, kind.ns, kind.arch,
278                                                  kind.value))
279       return StringRef();
280     return StringRef("unknown reference kind");
281   }
282
283   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
284 };
285
286 template <> struct ScalarEnumerationTraits<lld::File::Kind> {
287   static void enumeration(IO &io, lld::File::Kind &value) {
288     io.enumCase(value, "error-object",   lld::File::kindErrorObject);
289     io.enumCase(value, "object",         lld::File::kindMachObject);
290     io.enumCase(value, "shared-library", lld::File::kindSharedLibrary);
291     io.enumCase(value, "static-library", lld::File::kindArchiveLibrary);
292   }
293 };
294
295 template <> struct ScalarEnumerationTraits<lld::Atom::Scope> {
296   static void enumeration(IO &io, lld::Atom::Scope &value) {
297     io.enumCase(value, "global", lld::Atom::scopeGlobal);
298     io.enumCase(value, "hidden", lld::Atom::scopeLinkageUnit);
299     io.enumCase(value, "static", lld::Atom::scopeTranslationUnit);
300   }
301 };
302
303 template <> struct ScalarEnumerationTraits<lld::DefinedAtom::SectionChoice> {
304   static void enumeration(IO &io, lld::DefinedAtom::SectionChoice &value) {
305     io.enumCase(value, "content", lld::DefinedAtom::sectionBasedOnContent);
306     io.enumCase(value, "custom",  lld::DefinedAtom::sectionCustomPreferred);
307     io.enumCase(value, "custom-required",
308                                  lld::DefinedAtom::sectionCustomRequired);
309   }
310 };
311
312 template <> struct ScalarEnumerationTraits<lld::DefinedAtom::Interposable> {
313   static void enumeration(IO &io, lld::DefinedAtom::Interposable &value) {
314     io.enumCase(value, "no",           DefinedAtom::interposeNo);
315     io.enumCase(value, "yes",          DefinedAtom::interposeYes);
316     io.enumCase(value, "yes-and-weak", DefinedAtom::interposeYesAndRuntimeWeak);
317   }
318 };
319
320 template <> struct ScalarEnumerationTraits<lld::DefinedAtom::Merge> {
321   static void enumeration(IO &io, lld::DefinedAtom::Merge &value) {
322     io.enumCase(value, "no",           lld::DefinedAtom::mergeNo);
323     io.enumCase(value, "as-tentative", lld::DefinedAtom::mergeAsTentative);
324     io.enumCase(value, "as-weak",      lld::DefinedAtom::mergeAsWeak);
325     io.enumCase(value, "as-addressed-weak",
326                                    lld::DefinedAtom::mergeAsWeakAndAddressUsed);
327     io.enumCase(value, "by-content",   lld::DefinedAtom::mergeByContent);
328     io.enumCase(value, "same-name-and-size",
329                 lld::DefinedAtom::mergeSameNameAndSize);
330     io.enumCase(value, "largest", lld::DefinedAtom::mergeByLargestSection);
331   }
332 };
333
334 template <> struct ScalarEnumerationTraits<lld::DefinedAtom::DeadStripKind> {
335   static void enumeration(IO &io, lld::DefinedAtom::DeadStripKind &value) {
336     io.enumCase(value, "normal", lld::DefinedAtom::deadStripNormal);
337     io.enumCase(value, "never",  lld::DefinedAtom::deadStripNever);
338     io.enumCase(value, "always", lld::DefinedAtom::deadStripAlways);
339   }
340 };
341
342 template <> struct ScalarEnumerationTraits<lld::DefinedAtom::DynamicExport> {
343   static void enumeration(IO &io, lld::DefinedAtom::DynamicExport &value) {
344     io.enumCase(value, "normal", lld::DefinedAtom::dynamicExportNormal);
345     io.enumCase(value, "always", lld::DefinedAtom::dynamicExportAlways);
346   }
347 };
348
349 template <> struct ScalarEnumerationTraits<lld::DefinedAtom::CodeModel> {
350   static void enumeration(IO &io, lld::DefinedAtom::CodeModel &value) {
351     io.enumCase(value, "none", lld::DefinedAtom::codeNA);
352     io.enumCase(value, "mips-pic", lld::DefinedAtom::codeMipsPIC);
353     io.enumCase(value, "mips-micro", lld::DefinedAtom::codeMipsMicro);
354     io.enumCase(value, "mips-micro-pic", lld::DefinedAtom::codeMipsMicroPIC);
355     io.enumCase(value, "mips-16", lld::DefinedAtom::codeMips16);
356     io.enumCase(value, "arm-thumb", lld::DefinedAtom::codeARMThumb);
357     io.enumCase(value, "arm-a", lld::DefinedAtom::codeARM_a);
358     io.enumCase(value, "arm-d", lld::DefinedAtom::codeARM_d);
359     io.enumCase(value, "arm-t", lld::DefinedAtom::codeARM_t);
360   }
361 };
362
363 template <>
364 struct ScalarEnumerationTraits<lld::DefinedAtom::ContentPermissions> {
365   static void enumeration(IO &io, lld::DefinedAtom::ContentPermissions &value) {
366     io.enumCase(value, "---",     lld::DefinedAtom::perm___);
367     io.enumCase(value, "r--",     lld::DefinedAtom::permR__);
368     io.enumCase(value, "r-x",     lld::DefinedAtom::permR_X);
369     io.enumCase(value, "rw-",     lld::DefinedAtom::permRW_);
370     io.enumCase(value, "rwx",     lld::DefinedAtom::permRWX);
371     io.enumCase(value, "rw-l",    lld::DefinedAtom::permRW_L);
372     io.enumCase(value, "unknown", lld::DefinedAtom::permUnknown);
373   }
374 };
375
376 template <> struct ScalarEnumerationTraits<lld::DefinedAtom::ContentType> {
377   static void enumeration(IO &io, lld::DefinedAtom::ContentType &value) {
378     io.enumCase(value, "unknown",         DefinedAtom::typeUnknown);
379     io.enumCase(value, "code",            DefinedAtom::typeCode);
380     io.enumCase(value, "stub",            DefinedAtom::typeStub);
381     io.enumCase(value, "constant",        DefinedAtom::typeConstant);
382     io.enumCase(value, "data",            DefinedAtom::typeData);
383     io.enumCase(value, "quick-data",      DefinedAtom::typeDataFast);
384     io.enumCase(value, "zero-fill",       DefinedAtom::typeZeroFill);
385     io.enumCase(value, "zero-fill-quick", DefinedAtom::typeZeroFillFast);
386     io.enumCase(value, "const-data",      DefinedAtom::typeConstData);
387     io.enumCase(value, "got",             DefinedAtom::typeGOT);
388     io.enumCase(value, "resolver",        DefinedAtom::typeResolver);
389     io.enumCase(value, "branch-island",   DefinedAtom::typeBranchIsland);
390     io.enumCase(value, "branch-shim",     DefinedAtom::typeBranchShim);
391     io.enumCase(value, "stub-helper",     DefinedAtom::typeStubHelper);
392     io.enumCase(value, "c-string",        DefinedAtom::typeCString);
393     io.enumCase(value, "utf16-string",    DefinedAtom::typeUTF16String);
394     io.enumCase(value, "unwind-cfi",      DefinedAtom::typeCFI);
395     io.enumCase(value, "unwind-lsda",     DefinedAtom::typeLSDA);
396     io.enumCase(value, "const-4-byte",    DefinedAtom::typeLiteral4);
397     io.enumCase(value, "const-8-byte",    DefinedAtom::typeLiteral8);
398     io.enumCase(value, "const-16-byte",   DefinedAtom::typeLiteral16);
399     io.enumCase(value, "lazy-pointer",    DefinedAtom::typeLazyPointer);
400     io.enumCase(value, "lazy-dylib-pointer",
401                                           DefinedAtom::typeLazyDylibPointer);
402     io.enumCase(value, "cfstring",        DefinedAtom::typeCFString);
403     io.enumCase(value, "initializer-pointer",
404                                           DefinedAtom::typeInitializerPtr);
405     io.enumCase(value, "terminator-pointer",
406                                           DefinedAtom::typeTerminatorPtr);
407     io.enumCase(value, "c-string-pointer",DefinedAtom::typeCStringPtr);
408     io.enumCase(value, "objc-class-pointer",
409                                           DefinedAtom::typeObjCClassPtr);
410     io.enumCase(value, "objc-category-list",
411                                           DefinedAtom::typeObjC2CategoryList);
412     io.enumCase(value, "objc-image-info",
413                                           DefinedAtom::typeObjCImageInfo);
414     io.enumCase(value, "objc-method-list",
415                                           DefinedAtom::typeObjCMethodList);
416     io.enumCase(value, "objc-class1",     DefinedAtom::typeObjC1Class);
417     io.enumCase(value, "dtraceDOF",       DefinedAtom::typeDTraceDOF);
418     io.enumCase(value, "interposing-tuples",
419                                           DefinedAtom::typeInterposingTuples);
420     io.enumCase(value, "lto-temp",        DefinedAtom::typeTempLTO);
421     io.enumCase(value, "compact-unwind",  DefinedAtom::typeCompactUnwindInfo);
422     io.enumCase(value, "unwind-info",     DefinedAtom::typeProcessedUnwindInfo);
423     io.enumCase(value, "tlv-thunk",       DefinedAtom::typeThunkTLV);
424     io.enumCase(value, "tlv-data",        DefinedAtom::typeTLVInitialData);
425     io.enumCase(value, "tlv-zero-fill",   DefinedAtom::typeTLVInitialZeroFill);
426     io.enumCase(value, "tlv-initializer-ptr",
427                                           DefinedAtom::typeTLVInitializerPtr);
428     io.enumCase(value, "mach_header",     DefinedAtom::typeMachHeader);
429     io.enumCase(value, "dso_handle",      DefinedAtom::typeDSOHandle);
430     io.enumCase(value, "sectcreate",      DefinedAtom::typeSectCreate);
431   }
432 };
433
434 template <> struct ScalarEnumerationTraits<lld::UndefinedAtom::CanBeNull> {
435   static void enumeration(IO &io, lld::UndefinedAtom::CanBeNull &value) {
436     io.enumCase(value, "never",       lld::UndefinedAtom::canBeNullNever);
437     io.enumCase(value, "at-runtime",  lld::UndefinedAtom::canBeNullAtRuntime);
438     io.enumCase(value, "at-buildtime",lld::UndefinedAtom::canBeNullAtBuildtime);
439   }
440 };
441
442 template <> struct ScalarEnumerationTraits<ShlibCanBeNull> {
443   static void enumeration(IO &io, ShlibCanBeNull &value) {
444     io.enumCase(value, "never",      false);
445     io.enumCase(value, "at-runtime", true);
446   }
447 };
448
449 template <>
450 struct ScalarEnumerationTraits<lld::SharedLibraryAtom::Type> {
451   static void enumeration(IO &io, lld::SharedLibraryAtom::Type &value) {
452     io.enumCase(value, "code",    lld::SharedLibraryAtom::Type::Code);
453     io.enumCase(value, "data",    lld::SharedLibraryAtom::Type::Data);
454     io.enumCase(value, "unknown", lld::SharedLibraryAtom::Type::Unknown);
455   }
456 };
457
458 /// This is a custom formatter for lld::DefinedAtom::Alignment.  Values look
459 /// like:
460 ///     8           # 8-byte aligned
461 ///     7 mod 16    # 16-byte aligned plus 7 bytes
462 template <> struct ScalarTraits<lld::DefinedAtom::Alignment> {
463   static void output(const lld::DefinedAtom::Alignment &value, void *ctxt,
464                      raw_ostream &out) {
465     if (value.modulus == 0) {
466       out << llvm::format("%d", value.value);
467     } else {
468       out << llvm::format("%d mod %d", value.modulus, value.value);
469     }
470   }
471
472   static StringRef input(StringRef scalar, void *ctxt,
473                          lld::DefinedAtom::Alignment &value) {
474     value.modulus = 0;
475     size_t modStart = scalar.find("mod");
476     if (modStart != StringRef::npos) {
477       StringRef modStr = scalar.slice(0, modStart);
478       modStr = modStr.rtrim();
479       unsigned int modulus;
480       if (modStr.getAsInteger(0, modulus)) {
481         return "malformed alignment modulus";
482       }
483       value.modulus = modulus;
484       scalar = scalar.drop_front(modStart + 3);
485       scalar = scalar.ltrim();
486     }
487     unsigned int power;
488     if (scalar.getAsInteger(0, power)) {
489       return "malformed alignment power";
490     }
491     value.value = power;
492     if (value.modulus >= power) {
493       return "malformed alignment, modulus too large for power";
494     }
495     return StringRef(); // returning empty string means success
496   }
497
498   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
499 };
500
501 template <> struct ScalarEnumerationTraits<FileKinds> {
502   static void enumeration(IO &io, FileKinds &value) {
503     io.enumCase(value, "object",        fileKindObjectAtoms);
504     io.enumCase(value, "archive",       fileKindArchive);
505     io.enumCase(value, "object-mach-o", fileKindObjectMachO);
506   }
507 };
508
509 template <> struct MappingTraits<ArchMember> {
510   static void mapping(IO &io, ArchMember &member) {
511     io.mapOptional("kind",    member._kind, fileKindObjectAtoms);
512     io.mapOptional("name",    member._name);
513     io.mapRequired("content", member._content);
514   }
515 };
516
517 // Declare that an AtomList is a yaml sequence.
518 template <typename T> struct SequenceTraits<AtomList<T> > {
519   static size_t size(IO &io, AtomList<T> &seq) { return seq._atoms.size(); }
520   static T *&element(IO &io, AtomList<T> &seq, size_t index) {
521     if (index >= seq._atoms.size())
522       seq._atoms.resize(index + 1);
523     return seq._atoms[index].get();
524   }
525 };
526
527 // Declare that an AtomRange is a yaml sequence.
528 template <typename T> struct SequenceTraits<File::AtomRange<T> > {
529   static size_t size(IO &io, File::AtomRange<T> &seq) { return seq.size(); }
530   static T *&element(IO &io, File::AtomRange<T> &seq, size_t index) {
531     assert(io.outputting() && "AtomRange only used when outputting");
532     assert(index < seq.size() && "Out of range access");
533     return seq[index].get();
534   }
535 };
536
537 // Used to allow DefinedAtom content bytes to be a flow sequence of
538 // two-digit hex numbers without the leading 0x (e.g. FF, 04, 0A)
539 template <> struct ScalarTraits<ImplicitHex8> {
540   static void output(const ImplicitHex8 &val, void *, raw_ostream &out) {
541     uint8_t num = val;
542     out << llvm::format("%02X", num);
543   }
544
545   static StringRef input(StringRef str, void *, ImplicitHex8 &val) {
546     unsigned long long n;
547     if (getAsUnsignedInteger(str, 16, n))
548       return "invalid two-digit-hex number";
549     if (n > 0xFF)
550       return "out of range two-digit-hex number";
551     val = n;
552     return StringRef(); // returning empty string means success
553   }
554
555   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
556 };
557
558 // YAML conversion for std::vector<const lld::File*>
559 template <> struct DocumentListTraits<std::vector<const lld::File *> > {
560   static size_t size(IO &io, std::vector<const lld::File *> &seq) {
561     return seq.size();
562   }
563   static const lld::File *&element(IO &io, std::vector<const lld::File *> &seq,
564                                    size_t index) {
565     if (index >= seq.size())
566       seq.resize(index + 1);
567     return seq[index];
568   }
569 };
570
571 // YAML conversion for const lld::File*
572 template <> struct MappingTraits<const lld::File *> {
573   class NormArchiveFile : public lld::ArchiveLibraryFile {
574   public:
575     NormArchiveFile(IO &io) : ArchiveLibraryFile("") {}
576
577     NormArchiveFile(IO &io, const lld::File *file)
578         : ArchiveLibraryFile(file->path()), _path(file->path()) {
579       // If we want to support writing archives, this constructor would
580       // need to populate _members.
581     }
582
583     const lld::File *denormalize(IO &io) { return this; }
584
585     const AtomRange<lld::DefinedAtom> defined() const override {
586       return _noDefinedAtoms;
587     }
588
589     const AtomRange<lld::UndefinedAtom> undefined() const override {
590       return _noUndefinedAtoms;
591     }
592
593     const AtomRange<lld::SharedLibraryAtom> sharedLibrary() const override {
594       return _noSharedLibraryAtoms;
595     }
596
597     const AtomRange<lld::AbsoluteAtom> absolute() const override {
598       return _noAbsoluteAtoms;
599     }
600
601     void clearAtoms() override {
602       _noDefinedAtoms.clear();
603       _noUndefinedAtoms.clear();
604       _noSharedLibraryAtoms.clear();
605       _noAbsoluteAtoms.clear();
606     }
607
608     File *find(StringRef name) override {
609       for (const ArchMember &member : _members)
610         for (const lld::DefinedAtom *atom : member._content->defined())
611           if (name == atom->name())
612             return const_cast<File *>(member._content);
613       return nullptr;
614     }
615
616     std::error_code
617     parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
618       return std::error_code();
619     }
620
621     StringRef               _path;
622     std::vector<ArchMember> _members;
623   };
624
625   class NormalizedFile : public lld::File {
626   public:
627     NormalizedFile(IO &io)
628       : File("", kindNormalizedObject), _io(io), _rnb(nullptr),
629         _definedAtomsRef(_definedAtoms._atoms),
630         _undefinedAtomsRef(_undefinedAtoms._atoms),
631         _sharedLibraryAtomsRef(_sharedLibraryAtoms._atoms),
632         _absoluteAtomsRef(_absoluteAtoms._atoms) {}
633
634     NormalizedFile(IO &io, const lld::File *file)
635         : File(file->path(), kindNormalizedObject), _io(io),
636           _rnb(new RefNameBuilder(*file)), _path(file->path()),
637         _definedAtomsRef(file->defined()),
638         _undefinedAtomsRef(file->undefined()),
639         _sharedLibraryAtomsRef(file->sharedLibrary()),
640         _absoluteAtomsRef(file->absolute()) {
641     }
642
643     ~NormalizedFile() override {
644     }
645
646     const lld::File *denormalize(IO &io);
647
648     const AtomRange<lld::DefinedAtom> defined() const override {
649       return _definedAtomsRef;
650     }
651
652     const AtomRange<lld::UndefinedAtom> undefined() const override {
653       return _undefinedAtomsRef;
654     }
655
656     const AtomRange<lld::SharedLibraryAtom> sharedLibrary() const override {
657       return _sharedLibraryAtomsRef;
658     }
659
660     const AtomRange<lld::AbsoluteAtom> absolute() const override {
661       return _absoluteAtomsRef;
662     }
663
664     void clearAtoms() override {
665       _definedAtoms._atoms.clear();
666       _undefinedAtoms._atoms.clear();
667       _sharedLibraryAtoms._atoms.clear();
668       _absoluteAtoms._atoms.clear();
669     }
670
671     // Allocate a new copy of this string in _storage, so the strings
672     // can be freed when File is destroyed.
673     StringRef copyString(StringRef str) {
674       char *s = _storage.Allocate<char>(str.size());
675       memcpy(s, str.data(), str.size());
676       return StringRef(s, str.size());
677     }
678
679     IO                                  &_io;
680     std::unique_ptr<RefNameBuilder>      _rnb;
681     StringRef                            _path;
682     AtomList<lld::DefinedAtom>           _definedAtoms;
683     AtomList<lld::UndefinedAtom>         _undefinedAtoms;
684     AtomList<lld::SharedLibraryAtom>     _sharedLibraryAtoms;
685     AtomList<lld::AbsoluteAtom>          _absoluteAtoms;
686     AtomRange<lld::DefinedAtom>          _definedAtomsRef;
687     AtomRange<lld::UndefinedAtom>        _undefinedAtomsRef;
688     AtomRange<lld::SharedLibraryAtom>    _sharedLibraryAtomsRef;
689     AtomRange<lld::AbsoluteAtom>         _absoluteAtomsRef;
690     llvm::BumpPtrAllocator               _storage;
691   };
692
693   static void mapping(IO &io, const lld::File *&file) {
694     YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
695     assert(info != nullptr);
696     // Let any register tag handler process this.
697     if (info->_registry && info->_registry->handleTaggedDoc(io, file))
698       return;
699     // If no registered handler claims this tag and there is no tag,
700     // grandfather in as "!native".
701     if (io.mapTag("!native", true) || io.mapTag("tag:yaml.org,2002:map"))
702       mappingAtoms(io, file);
703   }
704
705   static void mappingAtoms(IO &io, const lld::File *&file) {
706     YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
707     MappingNormalizationHeap<NormalizedFile, const lld::File *>
708       keys(io, file, nullptr);
709     assert(info != nullptr);
710     info->_file = keys.operator->();
711
712     io.mapOptional("path",                 keys->_path);
713
714     if (io.outputting()) {
715       io.mapOptional("defined-atoms",        keys->_definedAtomsRef);
716       io.mapOptional("undefined-atoms",      keys->_undefinedAtomsRef);
717       io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtomsRef);
718       io.mapOptional("absolute-atoms",       keys->_absoluteAtomsRef);
719     } else {
720       io.mapOptional("defined-atoms",        keys->_definedAtoms);
721       io.mapOptional("undefined-atoms",      keys->_undefinedAtoms);
722       io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtoms);
723       io.mapOptional("absolute-atoms",       keys->_absoluteAtoms);
724     }
725   }
726
727   static void mappingArchive(IO &io, const lld::File *&file) {
728     YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
729     MappingNormalizationHeap<NormArchiveFile, const lld::File *>
730       keys(io, file, &info->_file->allocator());
731
732     io.mapOptional("path",    keys->_path);
733     io.mapOptional("members", keys->_members);
734   }
735 };
736
737 // YAML conversion for const lld::Reference*
738 template <> struct MappingTraits<const lld::Reference *> {
739   class NormalizedReference : public lld::Reference {
740   public:
741     NormalizedReference(IO &io)
742         : lld::Reference(lld::Reference::KindNamespace::all,
743                          lld::Reference::KindArch::all, 0),
744           _target(nullptr), _offset(0), _addend(0), _tag(0) {}
745
746     NormalizedReference(IO &io, const lld::Reference *ref)
747         : lld::Reference(ref->kindNamespace(), ref->kindArch(),
748                          ref->kindValue()),
749           _target(nullptr), _targetName(targetName(io, ref)),
750           _offset(ref->offsetInAtom()), _addend(ref->addend()),
751           _tag(ref->tag()) {
752       _mappedKind.ns = ref->kindNamespace();
753       _mappedKind.arch = ref->kindArch();
754       _mappedKind.value = ref->kindValue();
755     }
756
757     const lld::Reference *denormalize(IO &io) {
758       YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
759       assert(info != nullptr);
760       typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
761       NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
762       if (!_targetName.empty())
763         _targetName = f->copyString(_targetName);
764       DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs()
765                                         << "created Reference to name: '"
766                                         << _targetName << "' ("
767                                         << (const void *)_targetName.data()
768                                         << ", " << _targetName.size() << ")\n");
769       setKindNamespace(_mappedKind.ns);
770       setKindArch(_mappedKind.arch);
771       setKindValue(_mappedKind.value);
772       return this;
773     }
774
775     void bind(const RefNameResolver &);
776     static StringRef targetName(IO &io, const lld::Reference *ref);
777
778     uint64_t offsetInAtom() const override { return _offset; }
779     const lld::Atom *target() const override { return _target; }
780     Addend addend() const override { return _addend; }
781     void setAddend(Addend a) override { _addend = a; }
782     void setTarget(const lld::Atom *a) override { _target = a; }
783
784     const lld::Atom *_target;
785     StringRef        _targetName;
786     uint32_t         _offset;
787     Addend           _addend;
788     RefKind          _mappedKind;
789     uint32_t         _tag;
790   };
791
792   static void mapping(IO &io, const lld::Reference *&ref) {
793     YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
794     MappingNormalizationHeap<NormalizedReference, const lld::Reference *> keys(
795         io, ref, &info->_file->allocator());
796
797     io.mapRequired("kind",   keys->_mappedKind);
798     io.mapOptional("offset", keys->_offset);
799     io.mapOptional("target", keys->_targetName);
800     io.mapOptional("addend", keys->_addend, (lld::Reference::Addend)0);
801     io.mapOptional("tag",    keys->_tag, 0u);
802   }
803 };
804
805 // YAML conversion for const lld::DefinedAtom*
806 template <> struct MappingTraits<const lld::DefinedAtom *> {
807
808   class NormalizedAtom : public lld::DefinedAtom {
809   public:
810     NormalizedAtom(IO &io)
811         : _file(fileFromContext(io)), _contentType(), _alignment(1) {
812       static uint32_t ordinalCounter = 1;
813       _ordinal = ordinalCounter++;
814     }
815
816     NormalizedAtom(IO &io, const lld::DefinedAtom *atom)
817         : _file(fileFromContext(io)), _name(atom->name()),
818           _scope(atom->scope()), _interpose(atom->interposable()),
819           _merge(atom->merge()), _contentType(atom->contentType()),
820           _alignment(atom->alignment()), _sectionChoice(atom->sectionChoice()),
821           _deadStrip(atom->deadStrip()), _dynamicExport(atom->dynamicExport()),
822           _codeModel(atom->codeModel()),
823           _permissions(atom->permissions()), _size(atom->size()),
824           _sectionName(atom->customSectionName()),
825           _sectionSize(atom->sectionSize()) {
826       for (const lld::Reference *r : *atom)
827         _references.push_back(r);
828       if (!atom->occupiesDiskSpace())
829         return;
830       ArrayRef<uint8_t> cont = atom->rawContent();
831       _content.reserve(cont.size());
832       for (uint8_t x : cont)
833         _content.push_back(x);
834     }
835
836     ~NormalizedAtom() override = default;
837
838     const lld::DefinedAtom *denormalize(IO &io) {
839       YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
840       assert(info != nullptr);
841       typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
842       NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
843       if (!_name.empty())
844         _name = f->copyString(_name);
845       if (!_refName.empty())
846         _refName = f->copyString(_refName);
847       if (!_sectionName.empty())
848         _sectionName = f->copyString(_sectionName);
849       DEBUG_WITH_TYPE("WriterYAML",
850                       llvm::dbgs() << "created DefinedAtom named: '" << _name
851                                    << "' (" << (const void *)_name.data()
852                                    << ", " << _name.size() << ")\n");
853       return this;
854     }
855
856     void bind(const RefNameResolver &);
857
858     // Extract current File object from YAML I/O parsing context
859     const lld::File &fileFromContext(IO &io) {
860       YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
861       assert(info != nullptr);
862       assert(info->_file != nullptr);
863       return *info->_file;
864     }
865
866     const lld::File &file() const override { return _file; }
867     StringRef name() const override { return _name; }
868     uint64_t size() const override { return _size; }
869     Scope scope() const override { return _scope; }
870     Interposable interposable() const override { return _interpose; }
871     Merge merge() const override { return _merge; }
872     ContentType contentType() const override { return _contentType; }
873     Alignment alignment() const override { return _alignment; }
874     SectionChoice sectionChoice() const override { return _sectionChoice; }
875     StringRef customSectionName() const override { return _sectionName; }
876     uint64_t sectionSize() const override { return _sectionSize; }
877     DeadStripKind deadStrip() const override { return _deadStrip; }
878     DynamicExport dynamicExport() const override { return _dynamicExport; }
879     CodeModel codeModel() const override { return _codeModel; }
880     ContentPermissions permissions() const override { return _permissions; }
881     ArrayRef<uint8_t> rawContent() const override {
882       if (!occupiesDiskSpace())
883         return ArrayRef<uint8_t>();
884       return ArrayRef<uint8_t>(
885           reinterpret_cast<const uint8_t *>(_content.data()), _content.size());
886     }
887
888     uint64_t ordinal() const override { return _ordinal; }
889
890     reference_iterator begin() const override {
891       uintptr_t index = 0;
892       const void *it = reinterpret_cast<const void *>(index);
893       return reference_iterator(*this, it);
894     }
895     reference_iterator end() const override {
896       uintptr_t index = _references.size();
897       const void *it = reinterpret_cast<const void *>(index);
898       return reference_iterator(*this, it);
899     }
900     const lld::Reference *derefIterator(const void *it) const override {
901       uintptr_t index = reinterpret_cast<uintptr_t>(it);
902       assert(index < _references.size());
903       return _references[index];
904     }
905     void incrementIterator(const void *&it) const override {
906       uintptr_t index = reinterpret_cast<uintptr_t>(it);
907       ++index;
908       it = reinterpret_cast<const void *>(index);
909     }
910
911     void addReference(Reference::KindNamespace ns,
912                       Reference::KindArch arch,
913                       Reference::KindValue kindValue, uint64_t off,
914                       const Atom *target, Reference::Addend a) override {
915       assert(target && "trying to create reference to nothing");
916       auto node = new (file().allocator()) SimpleReference(ns, arch, kindValue,
917                                                            off, target, a);
918       _references.push_back(node);
919     }
920
921     const lld::File                    &_file;
922     StringRef                           _name;
923     StringRef                           _refName;
924     Scope                               _scope;
925     Interposable                        _interpose;
926     Merge                               _merge;
927     ContentType                         _contentType;
928     Alignment                           _alignment;
929     SectionChoice                       _sectionChoice;
930     DeadStripKind                       _deadStrip;
931     DynamicExport                       _dynamicExport;
932     CodeModel                           _codeModel;
933     ContentPermissions                  _permissions;
934     uint32_t                            _ordinal;
935     std::vector<ImplicitHex8>           _content;
936     uint64_t                            _size;
937     StringRef                           _sectionName;
938     uint64_t                            _sectionSize;
939     std::vector<const lld::Reference *> _references;
940   };
941
942   static void mapping(IO &io, const lld::DefinedAtom *&atom) {
943     YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
944     MappingNormalizationHeap<NormalizedAtom, const lld::DefinedAtom *> keys(
945         io, atom, &info->_file->allocator());
946     if (io.outputting()) {
947       // If writing YAML, check if atom needs a ref-name.
948       typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
949       assert(info != nullptr);
950       NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
951       assert(f);
952       assert(f->_rnb);
953       if (f->_rnb->hasRefName(atom)) {
954         keys->_refName = f->_rnb->refName(atom);
955       }
956     }
957
958     io.mapOptional("name",             keys->_name,    StringRef());
959     io.mapOptional("ref-name",         keys->_refName, StringRef());
960     io.mapOptional("scope",            keys->_scope,
961                                          DefinedAtom::scopeTranslationUnit);
962     io.mapOptional("type",             keys->_contentType,
963                                          DefinedAtom::typeCode);
964     io.mapOptional("content",          keys->_content);
965     io.mapOptional("size",             keys->_size, (uint64_t)keys->_content.size());
966     io.mapOptional("interposable",     keys->_interpose,
967                                          DefinedAtom::interposeNo);
968     io.mapOptional("merge",            keys->_merge, DefinedAtom::mergeNo);
969     io.mapOptional("alignment",        keys->_alignment,
970                                          DefinedAtom::Alignment(1));
971     io.mapOptional("section-choice",   keys->_sectionChoice,
972                                          DefinedAtom::sectionBasedOnContent);
973     io.mapOptional("section-name",     keys->_sectionName, StringRef());
974     io.mapOptional("section-size",     keys->_sectionSize, (uint64_t)0);
975     io.mapOptional("dead-strip",       keys->_deadStrip,
976                                          DefinedAtom::deadStripNormal);
977     io.mapOptional("dynamic-export",   keys->_dynamicExport,
978                                          DefinedAtom::dynamicExportNormal);
979     io.mapOptional("code-model",       keys->_codeModel, DefinedAtom::codeNA);
980     // default permissions based on content type
981     io.mapOptional("permissions",      keys->_permissions,
982                                          DefinedAtom::permissions(
983                                                           keys->_contentType));
984     io.mapOptional("references",       keys->_references);
985   }
986 };
987
988 template <> struct MappingTraits<lld::DefinedAtom *> {
989   static void mapping(IO &io, lld::DefinedAtom *&atom) {
990     const lld::DefinedAtom *atomPtr = atom;
991     MappingTraits<const lld::DefinedAtom *>::mapping(io, atomPtr);
992     atom = const_cast<lld::DefinedAtom *>(atomPtr);
993   }
994 };
995
996 // YAML conversion for const lld::UndefinedAtom*
997 template <> struct MappingTraits<const lld::UndefinedAtom *> {
998   class NormalizedAtom : public lld::UndefinedAtom {
999   public:
1000     NormalizedAtom(IO &io)
1001         : _file(fileFromContext(io)), _canBeNull(canBeNullNever) {}
1002
1003     NormalizedAtom(IO &io, const lld::UndefinedAtom *atom)
1004         : _file(fileFromContext(io)), _name(atom->name()),
1005           _canBeNull(atom->canBeNull()) {}
1006
1007     ~NormalizedAtom() override = default;
1008
1009     const lld::UndefinedAtom *denormalize(IO &io) {
1010       YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1011       assert(info != nullptr);
1012       typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
1013       NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
1014       if (!_name.empty())
1015         _name = f->copyString(_name);
1016
1017       DEBUG_WITH_TYPE("WriterYAML",
1018                       llvm::dbgs() << "created UndefinedAtom named: '" << _name
1019                       << "' (" << (const void *)_name.data() << ", "
1020                       << _name.size() << ")\n");
1021       return this;
1022     }
1023
1024     // Extract current File object from YAML I/O parsing context
1025     const lld::File &fileFromContext(IO &io) {
1026       YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1027       assert(info != nullptr);
1028       assert(info->_file != nullptr);
1029       return *info->_file;
1030     }
1031
1032     const lld::File &file() const override { return _file; }
1033     StringRef name() const override { return _name; }
1034     CanBeNull canBeNull() const override { return _canBeNull; }
1035
1036     const lld::File     &_file;
1037     StringRef            _name;
1038     CanBeNull            _canBeNull;
1039   };
1040
1041   static void mapping(IO &io, const lld::UndefinedAtom *&atom) {
1042     YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1043     MappingNormalizationHeap<NormalizedAtom, const lld::UndefinedAtom *> keys(
1044         io, atom, &info->_file->allocator());
1045
1046     io.mapRequired("name",        keys->_name);
1047     io.mapOptional("can-be-null", keys->_canBeNull,
1048                                   lld::UndefinedAtom::canBeNullNever);
1049   }
1050 };
1051
1052 template <> struct MappingTraits<lld::UndefinedAtom *> {
1053   static void mapping(IO &io, lld::UndefinedAtom *&atom) {
1054     const lld::UndefinedAtom *atomPtr = atom;
1055     MappingTraits<const lld::UndefinedAtom *>::mapping(io, atomPtr);
1056     atom = const_cast<lld::UndefinedAtom *>(atomPtr);
1057   }
1058 };
1059
1060 // YAML conversion for const lld::SharedLibraryAtom*
1061 template <> struct MappingTraits<const lld::SharedLibraryAtom *> {
1062   class NormalizedAtom : public lld::SharedLibraryAtom {
1063   public:
1064     NormalizedAtom(IO &io)
1065         : _file(fileFromContext(io)), _canBeNull(false),
1066           _type(Type::Unknown), _size(0) {}
1067
1068     NormalizedAtom(IO &io, const lld::SharedLibraryAtom *atom)
1069         : _file(fileFromContext(io)), _name(atom->name()),
1070           _loadName(atom->loadName()), _canBeNull(atom->canBeNullAtRuntime()),
1071           _type(atom->type()), _size(atom->size()) {}
1072
1073     ~NormalizedAtom() override = default;
1074
1075     const lld::SharedLibraryAtom *denormalize(IO &io) {
1076       YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1077       assert(info != nullptr);
1078       typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
1079       NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
1080       if (!_name.empty())
1081         _name = f->copyString(_name);
1082       if (!_loadName.empty())
1083         _loadName = f->copyString(_loadName);
1084
1085       DEBUG_WITH_TYPE("WriterYAML",
1086                       llvm::dbgs() << "created SharedLibraryAtom named: '"
1087                                    << _name << "' ("
1088                                    << (const void *)_name.data()
1089                                    << ", " << _name.size() << ")\n");
1090       return this;
1091     }
1092
1093     // Extract current File object from YAML I/O parsing context
1094     const lld::File &fileFromContext(IO &io) {
1095       YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1096       assert(info != nullptr);
1097       assert(info->_file != nullptr);
1098       return *info->_file;
1099     }
1100
1101     const lld::File &file() const override { return _file; }
1102     StringRef name() const override { return _name; }
1103     StringRef loadName() const override { return _loadName; }
1104     bool canBeNullAtRuntime() const override { return _canBeNull; }
1105     Type type() const override { return _type; }
1106     uint64_t size() const override { return _size; }
1107
1108     const lld::File &_file;
1109     StringRef        _name;
1110     StringRef        _loadName;
1111     ShlibCanBeNull   _canBeNull;
1112     Type             _type;
1113     uint64_t         _size;
1114   };
1115
1116   static void mapping(IO &io, const lld::SharedLibraryAtom *&atom) {
1117
1118     YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1119     MappingNormalizationHeap<NormalizedAtom, const lld::SharedLibraryAtom *>
1120     keys(io, atom, &info->_file->allocator());
1121
1122     io.mapRequired("name",        keys->_name);
1123     io.mapOptional("load-name",   keys->_loadName);
1124     io.mapOptional("can-be-null", keys->_canBeNull, (ShlibCanBeNull) false);
1125     io.mapOptional("type",        keys->_type, SharedLibraryAtom::Type::Code);
1126     io.mapOptional("size",        keys->_size, uint64_t(0));
1127   }
1128 };
1129
1130 template <> struct MappingTraits<lld::SharedLibraryAtom *> {
1131   static void mapping(IO &io, lld::SharedLibraryAtom *&atom) {
1132     const lld::SharedLibraryAtom *atomPtr = atom;
1133     MappingTraits<const lld::SharedLibraryAtom *>::mapping(io, atomPtr);
1134     atom = const_cast<lld::SharedLibraryAtom *>(atomPtr);
1135   }
1136 };
1137
1138 // YAML conversion for const lld::AbsoluteAtom*
1139 template <> struct MappingTraits<const lld::AbsoluteAtom *> {
1140   class NormalizedAtom : public lld::AbsoluteAtom {
1141   public:
1142     NormalizedAtom(IO &io)
1143         : _file(fileFromContext(io)), _scope(), _value(0) {}
1144
1145     NormalizedAtom(IO &io, const lld::AbsoluteAtom *atom)
1146         : _file(fileFromContext(io)), _name(atom->name()),
1147           _scope(atom->scope()), _value(atom->value()) {}
1148
1149     ~NormalizedAtom() override = default;
1150
1151     const lld::AbsoluteAtom *denormalize(IO &io) {
1152       YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1153       assert(info != nullptr);
1154       typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
1155       NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
1156       if (!_name.empty())
1157         _name = f->copyString(_name);
1158
1159       DEBUG_WITH_TYPE("WriterYAML",
1160                       llvm::dbgs() << "created AbsoluteAtom named: '" << _name
1161                                    << "' (" << (const void *)_name.data()
1162                                    << ", " << _name.size() << ")\n");
1163       return this;
1164     }
1165
1166     // Extract current File object from YAML I/O parsing context
1167     const lld::File &fileFromContext(IO &io) {
1168       YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1169       assert(info != nullptr);
1170       assert(info->_file != nullptr);
1171       return *info->_file;
1172     }
1173
1174     const lld::File &file() const override { return _file; }
1175     StringRef name() const override { return _name; }
1176     uint64_t value() const override { return _value; }
1177     Scope scope() const override { return _scope; }
1178
1179     const lld::File &_file;
1180     StringRef        _name;
1181     StringRef        _refName;
1182     Scope            _scope;
1183     Hex64            _value;
1184   };
1185
1186   static void mapping(IO &io, const lld::AbsoluteAtom *&atom) {
1187     YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1188     MappingNormalizationHeap<NormalizedAtom, const lld::AbsoluteAtom *> keys(
1189         io, atom, &info->_file->allocator());
1190
1191     if (io.outputting()) {
1192       typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
1193       YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1194       assert(info != nullptr);
1195       NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
1196       assert(f);
1197       assert(f->_rnb);
1198       if (f->_rnb->hasRefName(atom)) {
1199         keys->_refName = f->_rnb->refName(atom);
1200       }
1201     }
1202
1203     io.mapRequired("name",     keys->_name);
1204     io.mapOptional("ref-name", keys->_refName, StringRef());
1205     io.mapOptional("scope",    keys->_scope);
1206     io.mapRequired("value",    keys->_value);
1207   }
1208 };
1209
1210 template <> struct MappingTraits<lld::AbsoluteAtom *> {
1211   static void mapping(IO &io, lld::AbsoluteAtom *&atom) {
1212     const lld::AbsoluteAtom *atomPtr = atom;
1213     MappingTraits<const lld::AbsoluteAtom *>::mapping(io, atomPtr);
1214     atom = const_cast<lld::AbsoluteAtom *>(atomPtr);
1215   }
1216 };
1217
1218 } // end namespace llvm
1219 } // end namespace yaml
1220
1221 RefNameResolver::RefNameResolver(const lld::File *file, IO &io) : _io(io) {
1222   typedef MappingTraits<const lld::DefinedAtom *>::NormalizedAtom
1223   NormalizedAtom;
1224   for (const lld::DefinedAtom *a : file->defined()) {
1225     const auto *na = (const NormalizedAtom *)a;
1226     if (!na->_refName.empty())
1227       add(na->_refName, a);
1228     else if (!na->_name.empty())
1229       add(na->_name, a);
1230   }
1231
1232   for (const lld::UndefinedAtom *a : file->undefined())
1233     add(a->name(), a);
1234
1235   for (const lld::SharedLibraryAtom *a : file->sharedLibrary())
1236     add(a->name(), a);
1237
1238   typedef MappingTraits<const lld::AbsoluteAtom *>::NormalizedAtom NormAbsAtom;
1239   for (const lld::AbsoluteAtom *a : file->absolute()) {
1240     const auto *na = (const NormAbsAtom *)a;
1241     if (na->_refName.empty())
1242       add(na->_name, a);
1243     else
1244       add(na->_refName, a);
1245   }
1246 }
1247
1248 inline const lld::File *
1249 MappingTraits<const lld::File *>::NormalizedFile::denormalize(IO &io) {
1250   typedef MappingTraits<const lld::DefinedAtom *>::NormalizedAtom
1251   NormalizedAtom;
1252
1253   RefNameResolver nameResolver(this, io);
1254   // Now that all atoms are parsed, references can be bound.
1255   for (const lld::DefinedAtom *a : this->defined()) {
1256     auto *normAtom = (NormalizedAtom *)const_cast<DefinedAtom *>(a);
1257     normAtom->bind(nameResolver);
1258   }
1259
1260   return this;
1261 }
1262
1263 inline void MappingTraits<const lld::DefinedAtom *>::NormalizedAtom::bind(
1264     const RefNameResolver &resolver) {
1265   typedef MappingTraits<const lld::Reference *>::NormalizedReference
1266   NormalizedReference;
1267   for (const lld::Reference *ref : _references) {
1268     auto *normRef = (NormalizedReference *)const_cast<Reference *>(ref);
1269     normRef->bind(resolver);
1270   }
1271 }
1272
1273 inline void MappingTraits<const lld::Reference *>::NormalizedReference::bind(
1274     const RefNameResolver &resolver) {
1275   _target = resolver.lookup(_targetName);
1276 }
1277
1278 inline StringRef
1279 MappingTraits<const lld::Reference *>::NormalizedReference::targetName(
1280     IO &io, const lld::Reference *ref) {
1281   if (ref->target() == nullptr)
1282     return StringRef();
1283   YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
1284   assert(info != nullptr);
1285   typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
1286   NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
1287   RefNameBuilder &rnb = *f->_rnb;
1288   if (rnb.hasRefName(ref->target()))
1289     return rnb.refName(ref->target());
1290   return ref->target()->name();
1291 }
1292
1293 namespace lld {
1294 namespace yaml {
1295
1296 class Writer : public lld::Writer {
1297 public:
1298   Writer(const LinkingContext &context) : _ctx(context) {}
1299
1300   llvm::Error writeFile(const lld::File &file, StringRef outPath) override {
1301     // Create stream to path.
1302     std::error_code ec;
1303     llvm::raw_fd_ostream out(outPath, ec, llvm::sys::fs::F_Text);
1304     if (ec)
1305       return llvm::errorCodeToError(ec);
1306
1307     // Create yaml Output writer, using yaml options for context.
1308     YamlContext yamlContext;
1309     yamlContext._ctx = &_ctx;
1310     yamlContext._registry = &_ctx.registry();
1311     llvm::yaml::Output yout(out, &yamlContext);
1312
1313     // Write yaml output.
1314     const lld::File *fileRef = &file;
1315     yout << fileRef;
1316
1317     return llvm::Error::success();
1318   }
1319
1320 private:
1321   const LinkingContext &_ctx;
1322 };
1323
1324 } // end namespace yaml
1325
1326 namespace {
1327
1328 /// Handles !native tagged yaml documents.
1329 class NativeYamlIOTaggedDocumentHandler : public YamlIOTaggedDocumentHandler {
1330   bool handledDocTag(llvm::yaml::IO &io, const lld::File *&file) const override {
1331     if (io.mapTag("!native")) {
1332       MappingTraits<const lld::File *>::mappingAtoms(io, file);
1333       return true;
1334     }
1335     return false;
1336   }
1337 };
1338
1339 /// Handles !archive tagged yaml documents.
1340 class ArchiveYamlIOTaggedDocumentHandler : public YamlIOTaggedDocumentHandler {
1341   bool handledDocTag(llvm::yaml::IO &io, const lld::File *&file) const override {
1342     if (io.mapTag("!archive")) {
1343       MappingTraits<const lld::File *>::mappingArchive(io, file);
1344       return true;
1345     }
1346     return false;
1347   }
1348 };
1349
1350 class YAMLReader : public Reader {
1351 public:
1352   YAMLReader(const Registry &registry) : _registry(registry) {}
1353
1354   bool canParse(file_magic magic, MemoryBufferRef mb) const override {
1355     StringRef name = mb.getBufferIdentifier();
1356     return name.endswith(".objtxt") || name.endswith(".yaml");
1357   }
1358
1359   ErrorOr<std::unique_ptr<File>>
1360   loadFile(std::unique_ptr<MemoryBuffer> mb,
1361            const class Registry &) const override {
1362     // Create YAML Input Reader.
1363     YamlContext yamlContext;
1364     yamlContext._registry = &_registry;
1365     yamlContext._path = mb->getBufferIdentifier();
1366     llvm::yaml::Input yin(mb->getBuffer(), &yamlContext);
1367
1368     // Fill vector with File objects created by parsing yaml.
1369     std::vector<const lld::File *> createdFiles;
1370     yin >> createdFiles;
1371     assert(createdFiles.size() == 1);
1372
1373     // Error out now if there were parsing errors.
1374     if (yin.error())
1375       return make_error_code(lld::YamlReaderError::illegal_value);
1376
1377     std::shared_ptr<MemoryBuffer> smb(mb.release());
1378     const File *file = createdFiles[0];
1379     // Note: loadFile() should return vector of *const* File
1380     File *f = const_cast<File *>(file);
1381     f->setLastError(std::error_code());
1382     f->setSharedMemoryBuffer(smb);
1383     return std::unique_ptr<File>(f);
1384   }
1385
1386 private:
1387   const Registry &_registry;
1388 };
1389
1390 } // end anonymous namespace
1391
1392 void Registry::addSupportYamlFiles() {
1393   add(std::unique_ptr<Reader>(new YAMLReader(*this)));
1394   add(std::unique_ptr<YamlIOTaggedDocumentHandler>(
1395                                     new NativeYamlIOTaggedDocumentHandler()));
1396   add(std::unique_ptr<YamlIOTaggedDocumentHandler>(
1397                                     new ArchiveYamlIOTaggedDocumentHandler()));
1398 }
1399
1400 std::unique_ptr<Writer> createWriterYAML(const LinkingContext &context) {
1401   return std::unique_ptr<Writer>(new lld::yaml::Writer(context));
1402 }
1403
1404 } // end namespace lld