OSDN Git Service

[CallSiteSplitting] Report edge deletion to DomTreeUpdater
[android-x86/external-llvm.git] / lib / TextAPI / MachO / TextStub.cpp
1 //===- llvm/TextAPI/TextStub.cpp - Text Stub --------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief Implements the text stub file reader/writer.
12 ///
13 //===----------------------------------------------------------------------===//
14
15 #include "TextAPIContext.h"
16 #include "TextStubCommon.h"
17 #include "llvm/ADT/BitmaskEnum.h"
18 #include "llvm/ADT/SmallString.h"
19 #include "llvm/ADT/StringRef.h"
20 #include "llvm/Support/Allocator.h"
21 #include "llvm/Support/SourceMgr.h"
22 #include "llvm/Support/YAMLTraits.h"
23 #include "llvm/Support/raw_ostream.h"
24 #include "llvm/TextAPI/MachO/Architecture.h"
25 #include "llvm/TextAPI/MachO/ArchitectureSet.h"
26 #include "llvm/TextAPI/MachO/InterfaceFile.h"
27 #include "llvm/TextAPI/MachO/PackedVersion.h"
28 #include "llvm/TextAPI/MachO/TextAPIReader.h"
29 #include "llvm/TextAPI/MachO/TextAPIWriter.h"
30 #include <algorithm>
31 #include <set>
32
33 // clang-format off
34 /*
35
36  YAML Format specification.
37
38  The TBD v1 format only support two level address libraries and is per
39  definition application extension safe.
40
41 ---                              # the tag !tapi-tbd-v1 is optional and
42                                  # shouldn't be emitted to support older linker.
43 archs: [ armv7, armv7s, arm64 ]  # the list of architecture slices that are
44                                  # supported by this file.
45 platform: ios                    # Specifies the platform (macosx, ios, etc)
46 install-name: /u/l/libfoo.dylib  #
47 current-version: 1.2.3           # Optional: defaults to 1.0
48 compatibility-version: 1.0       # Optional: defaults to 1.0
49 swift-version: 0                 # Optional: defaults to 0
50 objc-constraint: none            # Optional: defaults to none
51 exports:                         # List of export sections
52 ...
53
54 Each export section is defined as following:
55
56  - archs: [ arm64 ]                   # the list of architecture slices
57    allowed-clients: [ client ]        # Optional: List of clients
58    re-exports: [ ]                    # Optional: List of re-exports
59    symbols: [ _sym ]                  # Optional: List of symbols
60    objc-classes: []                   # Optional: List of Objective-C classes
61    objc-ivars: []                     # Optional: List of Objective C Instance
62                                       #           Variables
63    weak-def-symbols: []               # Optional: List of weak defined symbols
64    thread-local-symbols: []           # Optional: List of thread local symbols
65 */
66
67 /*
68
69  YAML Format specification.
70
71 --- !tapi-tbd-v2
72 archs: [ armv7, armv7s, arm64 ]  # the list of architecture slices that are
73                                  # supported by this file.
74 uuids: [ armv7:... ]             # Optional: List of architecture and UUID pairs.
75 platform: ios                    # Specifies the platform (macosx, ios, etc)
76 flags: []                        # Optional:
77 install-name: /u/l/libfoo.dylib  #
78 current-version: 1.2.3           # Optional: defaults to 1.0
79 compatibility-version: 1.0       # Optional: defaults to 1.0
80 swift-version: 0                 # Optional: defaults to 0
81 objc-constraint: retain_release  # Optional: defaults to retain_release
82 parent-umbrella:                 # Optional:
83 exports:                         # List of export sections
84 ...
85 undefineds:                      # List of undefineds sections
86 ...
87
88 Each export section is defined as following:
89
90 - archs: [ arm64 ]                   # the list of architecture slices
91   allowed-clients: [ client ]        # Optional: List of clients
92   re-exports: [ ]                    # Optional: List of re-exports
93   symbols: [ _sym ]                  # Optional: List of symbols
94   objc-classes: []                   # Optional: List of Objective-C classes
95   objc-ivars: []                     # Optional: List of Objective C Instance
96                                      #           Variables
97   weak-def-symbols: []               # Optional: List of weak defined symbols
98   thread-local-symbols: []           # Optional: List of thread local symbols
99
100 Each undefineds section is defined as following:
101 - archs: [ arm64 ]     # the list of architecture slices
102   symbols: [ _sym ]    # Optional: List of symbols
103   objc-classes: []     # Optional: List of Objective-C classes
104   objc-ivars: []       # Optional: List of Objective C Instance Variables
105   weak-ref-symbols: [] # Optional: List of weak defined symbols
106 */
107
108 /*
109
110  YAML Format specification.
111
112 --- !tapi-tbd-v3
113 archs: [ armv7, armv7s, arm64 ]  # the list of architecture slices that are
114                                  # supported by this file.
115 uuids: [ armv7:... ]             # Optional: List of architecture and UUID pairs.
116 platform: ios                    # Specifies the platform (macosx, ios, etc)
117 flags: []                        # Optional:
118 install-name: /u/l/libfoo.dylib  #
119 current-version: 1.2.3           # Optional: defaults to 1.0
120 compatibility-version: 1.0       # Optional: defaults to 1.0
121 swift-abi-version: 0             # Optional: defaults to 0
122 objc-constraint: retain_release  # Optional: defaults to retain_release
123 parent-umbrella:                 # Optional:
124 exports:                         # List of export sections
125 ...
126 undefineds:                      # List of undefineds sections
127 ...
128
129 Each export section is defined as following:
130
131 - archs: [ arm64 ]                   # the list of architecture slices
132   allowed-clients: [ client ]        # Optional: List of clients
133   re-exports: [ ]                    # Optional: List of re-exports
134   symbols: [ _sym ]                  # Optional: List of symbols
135   objc-classes: []                   # Optional: List of Objective-C classes
136   objc-eh-types: []                  # Optional: List of Objective-C classes
137                                      #           with EH
138   objc-ivars: []                     # Optional: List of Objective C Instance
139                                      #           Variables
140   weak-def-symbols: []               # Optional: List of weak defined symbols
141   thread-local-symbols: []           # Optional: List of thread local symbols
142
143 Each undefineds section is defined as following:
144 - archs: [ arm64 ]     # the list of architecture slices
145   symbols: [ _sym ]    # Optional: List of symbols
146   objc-classes: []     # Optional: List of Objective-C classes
147   objc-eh-types: []                  # Optional: List of Objective-C classes
148                                      #           with EH
149   objc-ivars: []       # Optional: List of Objective C Instance Variables
150   weak-ref-symbols: [] # Optional: List of weak defined symbols
151 */
152 // clang-format on
153
154 using namespace llvm;
155 using namespace llvm::yaml;
156 using namespace llvm::MachO;
157
158 namespace {
159 struct ExportSection {
160   std::vector<Architecture> Architectures;
161   std::vector<FlowStringRef> AllowableClients;
162   std::vector<FlowStringRef> ReexportedLibraries;
163   std::vector<FlowStringRef> Symbols;
164   std::vector<FlowStringRef> Classes;
165   std::vector<FlowStringRef> ClassEHs;
166   std::vector<FlowStringRef> IVars;
167   std::vector<FlowStringRef> WeakDefSymbols;
168   std::vector<FlowStringRef> TLVSymbols;
169 };
170
171 struct UndefinedSection {
172   std::vector<Architecture> Architectures;
173   std::vector<FlowStringRef> Symbols;
174   std::vector<FlowStringRef> Classes;
175   std::vector<FlowStringRef> ClassEHs;
176   std::vector<FlowStringRef> IVars;
177   std::vector<FlowStringRef> WeakRefSymbols;
178 };
179
180 // clang-format off
181 enum TBDFlags : unsigned {
182   None                         = 0U,
183   FlatNamespace                = 1U << 0,
184   NotApplicationExtensionSafe  = 1U << 1,
185   InstallAPI                   = 1U << 2,
186   LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/InstallAPI),
187 };
188 // clang-format on
189 } // end anonymous namespace.
190
191 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(Architecture)
192 LLVM_YAML_IS_SEQUENCE_VECTOR(ExportSection)
193 LLVM_YAML_IS_SEQUENCE_VECTOR(UndefinedSection)
194
195 namespace llvm {
196 namespace yaml {
197
198 template <> struct MappingTraits<ExportSection> {
199   static void mapping(IO &IO, ExportSection &Section) {
200     const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
201     assert((!Ctx || (Ctx && Ctx->FileKind != FileType::Invalid)) &&
202            "File type is not set in YAML context");
203
204     IO.mapRequired("archs", Section.Architectures);
205     if (Ctx->FileKind == FileType::TBD_V1)
206       IO.mapOptional("allowed-clients", Section.AllowableClients);
207     else
208       IO.mapOptional("allowable-clients", Section.AllowableClients);
209     IO.mapOptional("re-exports", Section.ReexportedLibraries);
210     IO.mapOptional("symbols", Section.Symbols);
211     IO.mapOptional("objc-classes", Section.Classes);
212     if (Ctx->FileKind == FileType::TBD_V3)
213       IO.mapOptional("objc-eh-types", Section.ClassEHs);
214     IO.mapOptional("objc-ivars", Section.IVars);
215     IO.mapOptional("weak-def-symbols", Section.WeakDefSymbols);
216     IO.mapOptional("thread-local-symbols", Section.TLVSymbols);
217   }
218 };
219
220 template <> struct MappingTraits<UndefinedSection> {
221   static void mapping(IO &IO, UndefinedSection &Section) {
222     const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
223     assert((!Ctx || (Ctx && Ctx->FileKind != FileType::Invalid)) &&
224            "File type is not set in YAML context");
225
226     IO.mapRequired("archs", Section.Architectures);
227     IO.mapOptional("symbols", Section.Symbols);
228     IO.mapOptional("objc-classes", Section.Classes);
229     if (Ctx->FileKind == FileType::TBD_V3)
230       IO.mapOptional("objc-eh-types", Section.ClassEHs);
231     IO.mapOptional("objc-ivars", Section.IVars);
232     IO.mapOptional("weak-ref-symbols", Section.WeakRefSymbols);
233   }
234 };
235
236 template <> struct ScalarBitSetTraits<TBDFlags> {
237   static void bitset(IO &IO, TBDFlags &Flags) {
238     IO.bitSetCase(Flags, "flat_namespace", TBDFlags::FlatNamespace);
239     IO.bitSetCase(Flags, "not_app_extension_safe",
240                   TBDFlags::NotApplicationExtensionSafe);
241     IO.bitSetCase(Flags, "installapi", TBDFlags::InstallAPI);
242   }
243 };
244
245 template <> struct MappingTraits<const InterfaceFile *> {
246   struct NormalizedTBD {
247     explicit NormalizedTBD(IO &IO) {}
248     NormalizedTBD(IO &IO, const InterfaceFile *&File) {
249       Architectures = File->getArchitectures();
250       UUIDs = File->uuids();
251       Platform = File->getPlatform();
252       InstallName = File->getInstallName();
253       CurrentVersion = PackedVersion(File->getCurrentVersion());
254       CompatibilityVersion = PackedVersion(File->getCompatibilityVersion());
255       SwiftABIVersion = File->getSwiftABIVersion();
256       ObjCConstraint = File->getObjCConstraint();
257
258       Flags = TBDFlags::None;
259       if (!File->isApplicationExtensionSafe())
260         Flags |= TBDFlags::NotApplicationExtensionSafe;
261
262       if (!File->isTwoLevelNamespace())
263         Flags |= TBDFlags::FlatNamespace;
264
265       if (File->isInstallAPI())
266         Flags |= TBDFlags::InstallAPI;
267
268       ParentUmbrella = File->getParentUmbrella();
269
270       std::set<ArchitectureSet> ArchSet;
271       for (const auto &Library : File->allowableClients())
272         ArchSet.insert(Library.getArchitectures());
273
274       for (const auto &Library : File->reexportedLibraries())
275         ArchSet.insert(Library.getArchitectures());
276
277       std::map<const Symbol *, ArchitectureSet> SymbolToArchSet;
278       for (const auto *Symbol : File->exports()) {
279         auto Architectures = Symbol->getArchitectures();
280         SymbolToArchSet[Symbol] = Architectures;
281         ArchSet.insert(Architectures);
282       }
283
284       for (auto Architectures : ArchSet) {
285         ExportSection Section;
286         Section.Architectures = Architectures;
287
288         for (const auto &Library : File->allowableClients())
289           if (Library.getArchitectures() == Architectures)
290             Section.AllowableClients.emplace_back(Library.getInstallName());
291
292         for (const auto &Library : File->reexportedLibraries())
293           if (Library.getArchitectures() == Architectures)
294             Section.ReexportedLibraries.emplace_back(Library.getInstallName());
295
296         for (const auto &SymArch : SymbolToArchSet) {
297           if (SymArch.second != Architectures)
298             continue;
299
300           const auto *Symbol = SymArch.first;
301           switch (Symbol->getKind()) {
302           case SymbolKind::GlobalSymbol:
303             if (Symbol->isWeakDefined())
304               Section.WeakDefSymbols.emplace_back(Symbol->getName());
305             else if (Symbol->isThreadLocalValue())
306               Section.TLVSymbols.emplace_back(Symbol->getName());
307             else
308               Section.Symbols.emplace_back(Symbol->getName());
309             break;
310           case SymbolKind::ObjectiveCClass:
311             if (File->getFileType() != FileType::TBD_V3)
312               Section.Classes.emplace_back(
313                   copyString("_" + Symbol->getName().str()));
314             else
315               Section.Classes.emplace_back(Symbol->getName());
316             break;
317           case SymbolKind::ObjectiveCClassEHType:
318             if (File->getFileType() != FileType::TBD_V3)
319               Section.Symbols.emplace_back(
320                   copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str()));
321             else
322               Section.ClassEHs.emplace_back(Symbol->getName());
323             break;
324           case SymbolKind::ObjectiveCInstanceVariable:
325             if (File->getFileType() != FileType::TBD_V3)
326               Section.IVars.emplace_back(
327                   copyString("_" + Symbol->getName().str()));
328             else
329               Section.IVars.emplace_back(Symbol->getName());
330             break;
331           }
332         }
333         llvm::sort(Section.Symbols.begin(), Section.Symbols.end());
334         llvm::sort(Section.Classes.begin(), Section.Classes.end());
335         llvm::sort(Section.ClassEHs.begin(), Section.ClassEHs.end());
336         llvm::sort(Section.IVars.begin(), Section.IVars.end());
337         llvm::sort(Section.WeakDefSymbols.begin(),
338                    Section.WeakDefSymbols.end());
339         llvm::sort(Section.TLVSymbols.begin(), Section.TLVSymbols.end());
340         Exports.emplace_back(std::move(Section));
341       }
342
343       ArchSet.clear();
344       SymbolToArchSet.clear();
345
346       for (const auto *Symbol : File->undefineds()) {
347         auto Architectures = Symbol->getArchitectures();
348         SymbolToArchSet[Symbol] = Architectures;
349         ArchSet.insert(Architectures);
350       }
351
352       for (auto Architectures : ArchSet) {
353         UndefinedSection Section;
354         Section.Architectures = Architectures;
355
356         for (const auto &SymArch : SymbolToArchSet) {
357           if (SymArch.second != Architectures)
358             continue;
359
360           const auto *Symbol = SymArch.first;
361           switch (Symbol->getKind()) {
362           case SymbolKind::GlobalSymbol:
363             if (Symbol->isWeakReferenced())
364               Section.WeakRefSymbols.emplace_back(Symbol->getName());
365             else
366               Section.Symbols.emplace_back(Symbol->getName());
367             break;
368           case SymbolKind::ObjectiveCClass:
369             if (File->getFileType() != FileType::TBD_V3)
370               Section.Classes.emplace_back(
371                   copyString("_" + Symbol->getName().str()));
372             else
373               Section.Classes.emplace_back(Symbol->getName());
374             break;
375           case SymbolKind::ObjectiveCClassEHType:
376             if (File->getFileType() != FileType::TBD_V3)
377               Section.Symbols.emplace_back(
378                   copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str()));
379             else
380               Section.ClassEHs.emplace_back(Symbol->getName());
381             break;
382           case SymbolKind::ObjectiveCInstanceVariable:
383             if (File->getFileType() != FileType::TBD_V3)
384               Section.IVars.emplace_back(
385                   copyString("_" + Symbol->getName().str()));
386             else
387               Section.IVars.emplace_back(Symbol->getName());
388             break;
389           }
390         }
391         llvm::sort(Section.Symbols.begin(), Section.Symbols.end());
392         llvm::sort(Section.Classes.begin(), Section.Classes.end());
393         llvm::sort(Section.ClassEHs.begin(), Section.ClassEHs.end());
394         llvm::sort(Section.IVars.begin(), Section.IVars.end());
395         llvm::sort(Section.WeakRefSymbols.begin(),
396                    Section.WeakRefSymbols.end());
397         Undefineds.emplace_back(std::move(Section));
398       }
399     }
400
401     const InterfaceFile *denormalize(IO &IO) {
402       auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
403       assert(Ctx);
404
405       auto *File = new InterfaceFile;
406       File->setPath(Ctx->Path);
407       File->setFileType(Ctx->FileKind);
408       for (auto &ID : UUIDs)
409         File->addUUID(ID.first, ID.second);
410       File->setPlatform(Platform);
411       File->setArchitectures(Architectures);
412       File->setInstallName(InstallName);
413       File->setCurrentVersion(CurrentVersion);
414       File->setCompatibilityVersion(CompatibilityVersion);
415       File->setSwiftABIVersion(SwiftABIVersion);
416       File->setObjCConstraint(ObjCConstraint);
417       File->setParentUmbrella(ParentUmbrella);
418
419       if (Ctx->FileKind == FileType::TBD_V1) {
420         File->setTwoLevelNamespace();
421         File->setApplicationExtensionSafe();
422       } else {
423         File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
424         File->setApplicationExtensionSafe(
425             !(Flags & TBDFlags::NotApplicationExtensionSafe));
426         File->setInstallAPI(Flags & TBDFlags::InstallAPI);
427       }
428
429       for (const auto &Section : Exports) {
430         for (const auto &Library : Section.AllowableClients)
431           File->addAllowableClient(Library, Section.Architectures);
432         for (const auto &Library : Section.ReexportedLibraries)
433           File->addReexportedLibrary(Library, Section.Architectures);
434
435         for (const auto &Symbol : Section.Symbols) {
436           if (Ctx->FileKind != FileType::TBD_V3 &&
437               Symbol.value.startswith("_OBJC_EHTYPE_$_"))
438             File->addSymbol(SymbolKind::ObjectiveCClassEHType,
439                             Symbol.value.drop_front(15), Section.Architectures);
440           else
441             File->addSymbol(SymbolKind::GlobalSymbol, Symbol,
442                             Section.Architectures);
443         }
444         for (auto &Symbol : Section.Classes) {
445           auto Name = Symbol.value;
446           if (Ctx->FileKind != FileType::TBD_V3)
447             Name = Name.drop_front();
448           File->addSymbol(SymbolKind::ObjectiveCClass, Name,
449                           Section.Architectures);
450         }
451         for (auto &Symbol : Section.ClassEHs)
452           File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol,
453                           Section.Architectures);
454         for (auto &Symbol : Section.IVars) {
455           auto Name = Symbol.value;
456           if (Ctx->FileKind != FileType::TBD_V3)
457             Name = Name.drop_front();
458           File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name,
459                           Section.Architectures);
460         }
461         for (auto &Symbol : Section.WeakDefSymbols)
462           File->addSymbol(SymbolKind::GlobalSymbol, Symbol,
463                           Section.Architectures, SymbolFlags::WeakDefined);
464         for (auto &Symbol : Section.TLVSymbols)
465           File->addSymbol(SymbolKind::GlobalSymbol, Symbol,
466                           Section.Architectures, SymbolFlags::ThreadLocalValue);
467       }
468
469       for (const auto &Section : Undefineds) {
470         for (auto &Symbol : Section.Symbols) {
471           if (Ctx->FileKind != FileType::TBD_V3 &&
472               Symbol.value.startswith("_OBJC_EHTYPE_$_"))
473             File->addSymbol(SymbolKind::ObjectiveCClassEHType,
474                             Symbol.value.drop_front(15), Section.Architectures,
475                             SymbolFlags::Undefined);
476           else
477             File->addSymbol(SymbolKind::GlobalSymbol, Symbol,
478                             Section.Architectures, SymbolFlags::Undefined);
479         }
480         for (auto &Symbol : Section.Classes) {
481           auto Name = Symbol.value;
482           if (Ctx->FileKind != FileType::TBD_V3)
483             Name = Name.drop_front();
484           File->addSymbol(SymbolKind::ObjectiveCClass, Name,
485                           Section.Architectures, SymbolFlags::Undefined);
486         }
487         for (auto &Symbol : Section.ClassEHs)
488           File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol,
489                           Section.Architectures, SymbolFlags::Undefined);
490         for (auto &Symbol : Section.IVars) {
491           auto Name = Symbol.value;
492           if (Ctx->FileKind != FileType::TBD_V3)
493             Name = Name.drop_front();
494           File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name,
495                           Section.Architectures, SymbolFlags::Undefined);
496         }
497         for (auto &Symbol : Section.WeakRefSymbols)
498           File->addSymbol(SymbolKind::GlobalSymbol, Symbol,
499                           Section.Architectures,
500                           SymbolFlags::Undefined | SymbolFlags::WeakReferenced);
501       }
502
503       return File;
504     }
505
506     llvm::BumpPtrAllocator Allocator;
507     StringRef copyString(StringRef String) {
508       if (String.empty())
509         return {};
510
511       void *Ptr = Allocator.Allocate(String.size(), 1);
512       memcpy(Ptr, String.data(), String.size());
513       return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
514     }
515
516     std::vector<Architecture> Architectures;
517     std::vector<UUID> UUIDs;
518     PlatformKind Platform{PlatformKind::unknown};
519     StringRef InstallName;
520     PackedVersion CurrentVersion;
521     PackedVersion CompatibilityVersion;
522     SwiftVersion SwiftABIVersion{0};
523     ObjCConstraintType ObjCConstraint{ObjCConstraintType::None};
524     TBDFlags Flags{TBDFlags::None};
525     StringRef ParentUmbrella;
526     std::vector<ExportSection> Exports;
527     std::vector<UndefinedSection> Undefineds;
528   };
529
530   static void mapping(IO &IO, const InterfaceFile *&File) {
531     auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
532     assert((!Ctx || !IO.outputting() ||
533             (Ctx && Ctx->FileKind != FileType::Invalid)) &&
534            "File type is not set in YAML context");
535     MappingNormalization<NormalizedTBD, const InterfaceFile *> Keys(IO, File);
536
537     // prope file type when reading.
538     if (!IO.outputting()) {
539       if (IO.mapTag("!tapi-tbd-v2", false))
540         Ctx->FileKind = FileType::TBD_V2;
541       else if (IO.mapTag("!tapi-tbd-v3", false))
542         Ctx->FileKind = FileType::TBD_V2;
543       else if (IO.mapTag("!tapi-tbd-v1", false) ||
544                IO.mapTag("tag:yaml.org,2002:map", false))
545         Ctx->FileKind = FileType::TBD_V1;
546       else {
547         IO.setError("unsupported file type");
548         return;
549       }
550     }
551
552     // Set file tyoe when writing.
553     if (IO.outputting()) {
554       switch (Ctx->FileKind) {
555       default:
556         llvm_unreachable("unexpected file type");
557       case FileType::TBD_V1:
558         // Don't write the tag into the .tbd file for TBD v1.
559         break;
560       case FileType::TBD_V2:
561         IO.mapTag("!tapi-tbd-v2", true);
562         break;
563       case FileType::TBD_V3:
564         IO.mapTag("!tapi-tbd-v3", true);
565         break;
566       }
567     }
568
569     IO.mapRequired("archs", Keys->Architectures);
570     if (Ctx->FileKind != FileType::TBD_V1)
571       IO.mapOptional("uuids", Keys->UUIDs);
572     IO.mapRequired("platform", Keys->Platform);
573     if (Ctx->FileKind != FileType::TBD_V1)
574       IO.mapOptional("flags", Keys->Flags, TBDFlags::None);
575     IO.mapRequired("install-name", Keys->InstallName);
576     IO.mapOptional("current-version", Keys->CurrentVersion,
577                    PackedVersion(1, 0, 0));
578     IO.mapOptional("compatibility-version", Keys->CompatibilityVersion,
579                    PackedVersion(1, 0, 0));
580     if (Ctx->FileKind != FileType::TBD_V3)
581       IO.mapOptional("swift-version", Keys->SwiftABIVersion, SwiftVersion(0));
582     else
583       IO.mapOptional("swift-abi-version", Keys->SwiftABIVersion,
584                      SwiftVersion(0));
585     IO.mapOptional("objc-constraint", Keys->ObjCConstraint,
586                    (Ctx->FileKind == FileType::TBD_V1)
587                        ? ObjCConstraintType::None
588                        : ObjCConstraintType::Retain_Release);
589     if (Ctx->FileKind != FileType::TBD_V1)
590       IO.mapOptional("parent-umbrella", Keys->ParentUmbrella, StringRef());
591     IO.mapOptional("exports", Keys->Exports);
592     if (Ctx->FileKind != FileType::TBD_V1)
593       IO.mapOptional("undefineds", Keys->Undefineds);
594   }
595 };
596
597 template <>
598 struct DocumentListTraits<std::vector<const MachO::InterfaceFile *>> {
599   static size_t size(IO &IO, std::vector<const MachO::InterfaceFile *> &Seq) {
600     return Seq.size();
601   }
602   static const InterfaceFile *&
603   element(IO &IO, std::vector<const InterfaceFile *> &Seq, size_t Index) {
604     if (Index >= Seq.size())
605       Seq.resize(Index + 1);
606     return Seq[Index];
607   }
608 };
609
610 } // end namespace yaml.
611
612 namespace MachO {
613 static void DiagHandler(const SMDiagnostic &Diag, void *Context) {
614   auto *File = static_cast<TextAPIContext *>(Context);
615   SmallString<1024> Message;
616   raw_svector_ostream S(Message);
617
618   SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), File->Path,
619                        Diag.getLineNo(), Diag.getColumnNo(), Diag.getKind(),
620                        Diag.getMessage(), Diag.getLineContents(),
621                        Diag.getRanges(), Diag.getFixIts());
622
623   NewDiag.print(nullptr, S);
624   File->ErrorMessage = ("malformed file\n" + Message).str();
625 }
626
627 Expected<std::unique_ptr<InterfaceFile>>
628 TextAPIReader::get(std::unique_ptr<MemoryBuffer> InputBuffer) {
629   TextAPIContext Ctx;
630   Ctx.Path = InputBuffer->getBufferIdentifier();
631   yaml::Input YAMLIn(InputBuffer->getBuffer(), &Ctx, DiagHandler, &Ctx);
632
633   // Fill vector with interface file objects created by parsing the YAML file.
634   std::vector<const InterfaceFile *> Files;
635   YAMLIn >> Files;
636
637   if (YAMLIn.error())
638     return make_error<StringError>(Ctx.ErrorMessage, YAMLIn.error());
639
640   auto *File = const_cast<InterfaceFile *>(Files.front());
641   return std::unique_ptr<InterfaceFile>(File);
642 }
643
644 Error TextAPIWriter::writeToStream(raw_ostream &OS, const InterfaceFile &File) {
645   TextAPIContext Ctx;
646   Ctx.Path = File.getPath();
647   Ctx.FileKind = File.getFileType();
648   llvm::yaml::Output YAMLOut(OS, &Ctx, /*WrapColumn=*/80);
649
650   std::vector<const InterfaceFile *> Files;
651   Files.emplace_back(&File);
652
653   // Stream out yaml.
654   YAMLOut << Files;
655
656   return Error::success();
657 }
658
659 } // end namespace MachO.
660 } // end namespace llvm.