xref: /llvm-project/llvm/lib/TextAPI/TextStub.cpp (revision b2b50980de240b3d89e0f9340b51d6d6079fd19d)
1 //===- TextStub.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 // Implements the text stub file reader/writer.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "TextAPIContext.h"
14 #include "TextStubCommon.h"
15 #include "llvm/ADT/BitmaskEnum.h"
16 #include "llvm/ADT/SmallString.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/Support/Allocator.h"
19 #include "llvm/Support/SourceMgr.h"
20 #include "llvm/Support/YAMLTraits.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include "llvm/TextAPI/Architecture.h"
23 #include "llvm/TextAPI/ArchitectureSet.h"
24 #include "llvm/TextAPI/InterfaceFile.h"
25 #include "llvm/TextAPI/PackedVersion.h"
26 #include "llvm/TextAPI/TextAPIReader.h"
27 #include "llvm/TextAPI/TextAPIWriter.h"
28 #include <algorithm>
29 #include <set>
30 
31 // clang-format off
32 /*
33 
34  YAML Format specification.
35 
36  The TBD v1 format only support two level address libraries and is per
37  definition application extension safe.
38 
39 ---                              # the tag !tapi-tbd-v1 is optional and
40                                  # shouldn't be emitted to support older linker.
41 archs: [ armv7, armv7s, arm64 ]  # the list of architecture slices that are
42                                  # supported by this file.
43 platform: ios                    # Specifies the platform (macosx, ios, etc)
44 install-name: /u/l/libfoo.dylib  #
45 current-version: 1.2.3           # Optional: defaults to 1.0
46 compatibility-version: 1.0       # Optional: defaults to 1.0
47 swift-version: 0                 # Optional: defaults to 0
48 objc-constraint: none            # Optional: defaults to none
49 exports:                         # List of export sections
50 ...
51 
52 Each export section is defined as following:
53 
54  - archs: [ arm64 ]                   # the list of architecture slices
55    allowed-clients: [ client ]        # Optional: List of clients
56    re-exports: [ ]                    # Optional: List of re-exports
57    symbols: [ _sym ]                  # Optional: List of symbols
58    objc-classes: []                   # Optional: List of Objective-C classes
59    objc-ivars: []                     # Optional: List of Objective C Instance
60                                       #           Variables
61    weak-def-symbols: []               # Optional: List of weak defined symbols
62    thread-local-symbols: []           # Optional: List of thread local symbols
63 */
64 
65 /*
66 
67  YAML Format specification.
68 
69 --- !tapi-tbd-v2
70 archs: [ armv7, armv7s, arm64 ]  # the list of architecture slices that are
71                                  # supported by this file.
72 uuids: [ armv7:... ]             # Optional: List of architecture and UUID pairs.
73 platform: ios                    # Specifies the platform (macosx, ios, etc)
74 flags: []                        # Optional:
75 install-name: /u/l/libfoo.dylib  #
76 current-version: 1.2.3           # Optional: defaults to 1.0
77 compatibility-version: 1.0       # Optional: defaults to 1.0
78 swift-version: 0                 # Optional: defaults to 0
79 objc-constraint: retain_release  # Optional: defaults to retain_release
80 parent-umbrella:                 # Optional:
81 exports:                         # List of export sections
82 ...
83 undefineds:                      # List of undefineds sections
84 ...
85 
86 Each export section is defined as following:
87 
88 - archs: [ arm64 ]                   # the list of architecture slices
89   allowed-clients: [ client ]        # Optional: List of clients
90   re-exports: [ ]                    # Optional: List of re-exports
91   symbols: [ _sym ]                  # Optional: List of symbols
92   objc-classes: []                   # Optional: List of Objective-C classes
93   objc-ivars: []                     # Optional: List of Objective C Instance
94                                      #           Variables
95   weak-def-symbols: []               # Optional: List of weak defined symbols
96   thread-local-symbols: []           # Optional: List of thread local symbols
97 
98 Each undefineds section is defined as following:
99 - archs: [ arm64 ]     # the list of architecture slices
100   symbols: [ _sym ]    # Optional: List of symbols
101   objc-classes: []     # Optional: List of Objective-C classes
102   objc-ivars: []       # Optional: List of Objective C Instance Variables
103   weak-ref-symbols: [] # Optional: List of weak defined symbols
104 */
105 
106 /*
107 
108  YAML Format specification.
109 
110 --- !tapi-tbd-v3
111 archs: [ armv7, armv7s, arm64 ]  # the list of architecture slices that are
112                                  # supported by this file.
113 uuids: [ armv7:... ]             # Optional: List of architecture and UUID pairs.
114 platform: ios                    # Specifies the platform (macosx, ios, etc)
115 flags: []                        # Optional:
116 install-name: /u/l/libfoo.dylib  #
117 current-version: 1.2.3           # Optional: defaults to 1.0
118 compatibility-version: 1.0       # Optional: defaults to 1.0
119 swift-abi-version: 0             # Optional: defaults to 0
120 objc-constraint: retain_release  # Optional: defaults to retain_release
121 parent-umbrella:                 # Optional:
122 exports:                         # List of export sections
123 ...
124 undefineds:                      # List of undefineds sections
125 ...
126 
127 Each export section is defined as following:
128 
129 - archs: [ arm64 ]                   # the list of architecture slices
130   allowed-clients: [ client ]        # Optional: List of clients
131   re-exports: [ ]                    # Optional: List of re-exports
132   symbols: [ _sym ]                  # Optional: List of symbols
133   objc-classes: []                   # Optional: List of Objective-C classes
134   objc-eh-types: []                  # Optional: List of Objective-C classes
135                                      #           with EH
136   objc-ivars: []                     # Optional: List of Objective C Instance
137                                      #           Variables
138   weak-def-symbols: []               # Optional: List of weak defined symbols
139   thread-local-symbols: []           # Optional: List of thread local symbols
140 
141 Each undefineds section is defined as following:
142 - archs: [ arm64 ]     # the list of architecture slices
143   symbols: [ _sym ]    # Optional: List of symbols
144   objc-classes: []     # Optional: List of Objective-C classes
145   objc-eh-types: []                  # Optional: List of Objective-C classes
146                                      #           with EH
147   objc-ivars: []       # Optional: List of Objective C Instance Variables
148   weak-ref-symbols: [] # Optional: List of weak defined symbols
149 */
150 
151 /*
152 
153  YAML Format specification.
154 
155 --- !tapi-tbd
156 tbd-version: 4                              # The tbd version for format
157 targets: [ armv7-ios, x86_64-maccatalyst ]  # The list of applicable tapi supported target triples
158 uuids:                                      # Optional: List of target and UUID pairs.
159   - target: armv7-ios
160     value: ...
161   - target: x86_64-maccatalyst
162     value: ...
163 flags: []                        # Optional:
164 install-name: /u/l/libfoo.dylib  #
165 current-version: 1.2.3           # Optional: defaults to 1.0
166 compatibility-version: 1.0       # Optional: defaults to 1.0
167 swift-abi-version: 0             # Optional: defaults to 0
168 parent-umbrella:                 # Optional:
169 allowable-clients:
170   - targets: [ armv7-ios ]       # Optional:
171     clients: [ clientA ]
172 exports:                         # List of export sections
173 ...
174 re-exports:                      # List of reexport sections
175 ...
176 undefineds:                      # List of undefineds sections
177 ...
178 
179 Each export and reexport  section is defined as following:
180 
181 - targets: [ arm64-macos ]                        # The list of target triples associated with symbols
182   symbols: [ _symA ]                              # Optional: List of symbols
183   objc-classes: []                                # Optional: List of Objective-C classes
184   objc-eh-types: []                               # Optional: List of Objective-C classes
185                                                   #           with EH
186   objc-ivars: []                                  # Optional: List of Objective C Instance
187                                                   #           Variables
188   weak-symbols: []                                # Optional: List of weak defined symbols
189   thread-local-symbols: []                        # Optional: List of thread local symbols
190 - targets: [ arm64-macos, x86_64-maccatalyst ]    # Optional: Targets for applicable additional symbols
191   symbols: [ _symB ]                              # Optional: List of symbols
192 
193 Each undefineds section is defined as following:
194 - targets: [ arm64-macos ]    # The list of target triples associated with symbols
195   symbols: [ _symC ]          # Optional: List of symbols
196   objc-classes: []            # Optional: List of Objective-C classes
197   objc-eh-types: []           # Optional: List of Objective-C classes
198                               #           with EH
199   objc-ivars: []              # Optional: List of Objective C Instance Variables
200   weak-symbols: []            # Optional: List of weak defined symbols
201 */
202 // clang-format on
203 
204 using namespace llvm;
205 using namespace llvm::yaml;
206 using namespace llvm::MachO;
207 
208 namespace {
209 struct ExportSection {
210   std::vector<Architecture> Architectures;
211   std::vector<FlowStringRef> AllowableClients;
212   std::vector<FlowStringRef> ReexportedLibraries;
213   std::vector<FlowStringRef> Symbols;
214   std::vector<FlowStringRef> Classes;
215   std::vector<FlowStringRef> ClassEHs;
216   std::vector<FlowStringRef> IVars;
217   std::vector<FlowStringRef> WeakDefSymbols;
218   std::vector<FlowStringRef> TLVSymbols;
219 };
220 
221 struct UndefinedSection {
222   std::vector<Architecture> Architectures;
223   std::vector<FlowStringRef> Symbols;
224   std::vector<FlowStringRef> Classes;
225   std::vector<FlowStringRef> ClassEHs;
226   std::vector<FlowStringRef> IVars;
227   std::vector<FlowStringRef> WeakRefSymbols;
228 };
229 
230 // Sections for direct target mapping in TBDv4
231 struct SymbolSection {
232   TargetList Targets;
233   std::vector<FlowStringRef> Symbols;
234   std::vector<FlowStringRef> Classes;
235   std::vector<FlowStringRef> ClassEHs;
236   std::vector<FlowStringRef> Ivars;
237   std::vector<FlowStringRef> WeakSymbols;
238   std::vector<FlowStringRef> TlvSymbols;
239 };
240 
241 struct MetadataSection {
242   enum Option { Clients, Libraries };
243   std::vector<Target> Targets;
244   std::vector<FlowStringRef> Values;
245 };
246 
247 struct UmbrellaSection {
248   std::vector<Target> Targets;
249   std::string Umbrella;
250 };
251 
252 // UUID's for TBDv4 are mapped to target not arch
253 struct UUIDv4 {
254   Target TargetID;
255   std::string Value;
256 
257   UUIDv4() = default;
258   UUIDv4(const Target &TargetID, const std::string &Value)
259       : TargetID(TargetID), Value(Value) {}
260 };
261 } // end anonymous namespace.
262 
263 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(Architecture)
264 LLVM_YAML_IS_SEQUENCE_VECTOR(ExportSection)
265 LLVM_YAML_IS_SEQUENCE_VECTOR(UndefinedSection)
266 // Specific to TBDv4
267 LLVM_YAML_IS_SEQUENCE_VECTOR(SymbolSection)
268 LLVM_YAML_IS_SEQUENCE_VECTOR(MetadataSection)
269 LLVM_YAML_IS_SEQUENCE_VECTOR(UmbrellaSection)
270 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(Target)
271 LLVM_YAML_IS_SEQUENCE_VECTOR(UUIDv4)
272 
273 namespace llvm {
274 namespace yaml {
275 
276 template <> struct MappingTraits<ExportSection> {
277   static void mapping(IO &IO, ExportSection &Section) {
278     const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
279     assert((!Ctx || (Ctx && Ctx->FileKind != FileType::Invalid)) &&
280            "File type is not set in YAML context");
281 
282     IO.mapRequired("archs", Section.Architectures);
283     if (Ctx->FileKind == FileType::TBD_V1)
284       IO.mapOptional("allowed-clients", Section.AllowableClients);
285     else
286       IO.mapOptional("allowable-clients", Section.AllowableClients);
287     IO.mapOptional("re-exports", Section.ReexportedLibraries);
288     IO.mapOptional("symbols", Section.Symbols);
289     IO.mapOptional("objc-classes", Section.Classes);
290     if (Ctx->FileKind == FileType::TBD_V3)
291       IO.mapOptional("objc-eh-types", Section.ClassEHs);
292     IO.mapOptional("objc-ivars", Section.IVars);
293     IO.mapOptional("weak-def-symbols", Section.WeakDefSymbols);
294     IO.mapOptional("thread-local-symbols", Section.TLVSymbols);
295   }
296 };
297 
298 template <> struct MappingTraits<UndefinedSection> {
299   static void mapping(IO &IO, UndefinedSection &Section) {
300     const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
301     assert((!Ctx || (Ctx && Ctx->FileKind != FileType::Invalid)) &&
302            "File type is not set in YAML context");
303 
304     IO.mapRequired("archs", Section.Architectures);
305     IO.mapOptional("symbols", Section.Symbols);
306     IO.mapOptional("objc-classes", Section.Classes);
307     if (Ctx->FileKind == FileType::TBD_V3)
308       IO.mapOptional("objc-eh-types", Section.ClassEHs);
309     IO.mapOptional("objc-ivars", Section.IVars);
310     IO.mapOptional("weak-ref-symbols", Section.WeakRefSymbols);
311   }
312 };
313 
314 template <> struct MappingTraits<SymbolSection> {
315   static void mapping(IO &IO, SymbolSection &Section) {
316     IO.mapRequired("targets", Section.Targets);
317     IO.mapOptional("symbols", Section.Symbols);
318     IO.mapOptional("objc-classes", Section.Classes);
319     IO.mapOptional("objc-eh-types", Section.ClassEHs);
320     IO.mapOptional("objc-ivars", Section.Ivars);
321     IO.mapOptional("weak-symbols", Section.WeakSymbols);
322     IO.mapOptional("thread-local-symbols", Section.TlvSymbols);
323   }
324 };
325 
326 template <> struct MappingTraits<UmbrellaSection> {
327   static void mapping(IO &IO, UmbrellaSection &Section) {
328     IO.mapRequired("targets", Section.Targets);
329     IO.mapRequired("umbrella", Section.Umbrella);
330   }
331 };
332 
333 template <> struct MappingTraits<UUIDv4> {
334   static void mapping(IO &IO, UUIDv4 &UUID) {
335     IO.mapRequired("target", UUID.TargetID);
336     IO.mapRequired("value", UUID.Value);
337   }
338 };
339 
340 template <>
341 struct MappingContextTraits<MetadataSection, MetadataSection::Option> {
342   static void mapping(IO &IO, MetadataSection &Section,
343                       MetadataSection::Option &OptionKind) {
344     IO.mapRequired("targets", Section.Targets);
345     switch (OptionKind) {
346     case MetadataSection::Option::Clients:
347       IO.mapRequired("clients", Section.Values);
348       return;
349     case MetadataSection::Option::Libraries:
350       IO.mapRequired("libraries", Section.Values);
351       return;
352     }
353     llvm_unreachable("unexpected option for metadata");
354   }
355 };
356 
357 template <> struct ScalarBitSetTraits<TBDFlags> {
358   static void bitset(IO &IO, TBDFlags &Flags) {
359     IO.bitSetCase(Flags, "flat_namespace", TBDFlags::FlatNamespace);
360     IO.bitSetCase(Flags, "not_app_extension_safe",
361                   TBDFlags::NotApplicationExtensionSafe);
362     IO.bitSetCase(Flags, "installapi", TBDFlags::InstallAPI);
363   }
364 };
365 
366 template <> struct ScalarTraits<Target> {
367   static void output(const Target &Value, void *, raw_ostream &OS) {
368     OS << Value.Arch << "-";
369     switch (Value.Platform) {
370     default:
371       OS << "unknown";
372       break;
373     case PLATFORM_MACOS:
374       OS << "macos";
375       break;
376     case PLATFORM_IOS:
377       OS << "ios";
378       break;
379     case PLATFORM_TVOS:
380       OS << "tvos";
381       break;
382     case PLATFORM_WATCHOS:
383       OS << "watchos";
384       break;
385     case PLATFORM_BRIDGEOS:
386       OS << "bridgeos";
387       break;
388     case PLATFORM_MACCATALYST:
389       OS << "maccatalyst";
390       break;
391     case PLATFORM_IOSSIMULATOR:
392       OS << "ios-simulator";
393       break;
394     case PLATFORM_TVOSSIMULATOR:
395       OS << "tvos-simulator";
396       break;
397     case PLATFORM_WATCHOSSIMULATOR:
398       OS << "watchos-simulator";
399       break;
400     case PLATFORM_DRIVERKIT:
401       OS << "driverkit";
402       break;
403     }
404   }
405 
406   static StringRef input(StringRef Scalar, void *, Target &Value) {
407     auto Result = Target::create(Scalar);
408     if (!Result) {
409       consumeError(Result.takeError());
410       return "unparsable target";
411     }
412 
413     Value = *Result;
414     if (Value.Arch == AK_unknown)
415       return "unknown architecture";
416     if (Value.Platform == PLATFORM_UNKNOWN)
417       return "unknown platform";
418 
419     return {};
420   }
421 
422   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
423 };
424 
425 template <> struct MappingTraits<const InterfaceFile *> {
426   struct NormalizedTBD {
427     explicit NormalizedTBD(IO &IO) {}
428     NormalizedTBD(IO &IO, const InterfaceFile *&File) {
429       Architectures = File->getArchitectures();
430       UUIDs = File->uuids();
431       Platforms = File->getPlatforms();
432       InstallName = File->getInstallName();
433       CurrentVersion = PackedVersion(File->getCurrentVersion());
434       CompatibilityVersion = PackedVersion(File->getCompatibilityVersion());
435       SwiftABIVersion = File->getSwiftABIVersion();
436       ObjCConstraint = File->getObjCConstraint();
437 
438       Flags = TBDFlags::None;
439       if (!File->isApplicationExtensionSafe())
440         Flags |= TBDFlags::NotApplicationExtensionSafe;
441 
442       if (!File->isTwoLevelNamespace())
443         Flags |= TBDFlags::FlatNamespace;
444 
445       if (File->isInstallAPI())
446         Flags |= TBDFlags::InstallAPI;
447 
448       if (!File->umbrellas().empty())
449         ParentUmbrella = File->umbrellas().begin()->second;
450 
451       std::set<ArchitectureSet> ArchSet;
452       for (const auto &Library : File->allowableClients())
453         ArchSet.insert(Library.getArchitectures());
454 
455       for (const auto &Library : File->reexportedLibraries())
456         ArchSet.insert(Library.getArchitectures());
457 
458       std::map<const Symbol *, ArchitectureSet> SymbolToArchSet;
459       for (const auto *Symbol : File->exports()) {
460         auto Architectures = Symbol->getArchitectures();
461         SymbolToArchSet[Symbol] = Architectures;
462         ArchSet.insert(Architectures);
463       }
464 
465       for (auto Architectures : ArchSet) {
466         ExportSection Section;
467         Section.Architectures = Architectures;
468 
469         for (const auto &Library : File->allowableClients())
470           if (Library.getArchitectures() == Architectures)
471             Section.AllowableClients.emplace_back(Library.getInstallName());
472 
473         for (const auto &Library : File->reexportedLibraries())
474           if (Library.getArchitectures() == Architectures)
475             Section.ReexportedLibraries.emplace_back(Library.getInstallName());
476 
477         for (const auto &SymArch : SymbolToArchSet) {
478           if (SymArch.second != Architectures)
479             continue;
480 
481           const auto *Symbol = SymArch.first;
482           switch (Symbol->getKind()) {
483           case SymbolKind::GlobalSymbol:
484             if (Symbol->isWeakDefined())
485               Section.WeakDefSymbols.emplace_back(Symbol->getName());
486             else if (Symbol->isThreadLocalValue())
487               Section.TLVSymbols.emplace_back(Symbol->getName());
488             else
489               Section.Symbols.emplace_back(Symbol->getName());
490             break;
491           case SymbolKind::ObjectiveCClass:
492             if (File->getFileType() != FileType::TBD_V3)
493               Section.Classes.emplace_back(
494                   copyString("_" + Symbol->getName().str()));
495             else
496               Section.Classes.emplace_back(Symbol->getName());
497             break;
498           case SymbolKind::ObjectiveCClassEHType:
499             if (File->getFileType() != FileType::TBD_V3)
500               Section.Symbols.emplace_back(
501                   copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str()));
502             else
503               Section.ClassEHs.emplace_back(Symbol->getName());
504             break;
505           case SymbolKind::ObjectiveCInstanceVariable:
506             if (File->getFileType() != FileType::TBD_V3)
507               Section.IVars.emplace_back(
508                   copyString("_" + Symbol->getName().str()));
509             else
510               Section.IVars.emplace_back(Symbol->getName());
511             break;
512           }
513         }
514         llvm::sort(Section.Symbols);
515         llvm::sort(Section.Classes);
516         llvm::sort(Section.ClassEHs);
517         llvm::sort(Section.IVars);
518         llvm::sort(Section.WeakDefSymbols);
519         llvm::sort(Section.TLVSymbols);
520         Exports.emplace_back(std::move(Section));
521       }
522 
523       ArchSet.clear();
524       SymbolToArchSet.clear();
525 
526       for (const auto *Symbol : File->undefineds()) {
527         auto Architectures = Symbol->getArchitectures();
528         SymbolToArchSet[Symbol] = Architectures;
529         ArchSet.insert(Architectures);
530       }
531 
532       for (auto Architectures : ArchSet) {
533         UndefinedSection Section;
534         Section.Architectures = Architectures;
535 
536         for (const auto &SymArch : SymbolToArchSet) {
537           if (SymArch.second != Architectures)
538             continue;
539 
540           const auto *Symbol = SymArch.first;
541           switch (Symbol->getKind()) {
542           case SymbolKind::GlobalSymbol:
543             if (Symbol->isWeakReferenced())
544               Section.WeakRefSymbols.emplace_back(Symbol->getName());
545             else
546               Section.Symbols.emplace_back(Symbol->getName());
547             break;
548           case SymbolKind::ObjectiveCClass:
549             if (File->getFileType() != FileType::TBD_V3)
550               Section.Classes.emplace_back(
551                   copyString("_" + Symbol->getName().str()));
552             else
553               Section.Classes.emplace_back(Symbol->getName());
554             break;
555           case SymbolKind::ObjectiveCClassEHType:
556             if (File->getFileType() != FileType::TBD_V3)
557               Section.Symbols.emplace_back(
558                   copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str()));
559             else
560               Section.ClassEHs.emplace_back(Symbol->getName());
561             break;
562           case SymbolKind::ObjectiveCInstanceVariable:
563             if (File->getFileType() != FileType::TBD_V3)
564               Section.IVars.emplace_back(
565                   copyString("_" + Symbol->getName().str()));
566             else
567               Section.IVars.emplace_back(Symbol->getName());
568             break;
569           }
570         }
571         llvm::sort(Section.Symbols);
572         llvm::sort(Section.Classes);
573         llvm::sort(Section.ClassEHs);
574         llvm::sort(Section.IVars);
575         llvm::sort(Section.WeakRefSymbols);
576         Undefineds.emplace_back(std::move(Section));
577       }
578     }
579 
580     // TBD v1 - TBD v3 files only support one platform and several
581     // architectures. It is possible to have more than one platform for TBD v3
582     // files, but the architectures don't apply to all
583     // platforms, specifically to filter out the i386 slice from
584     // platform macCatalyst.
585     TargetList synthesizeTargets(ArchitectureSet Architectures,
586                                  const PlatformSet &Platforms) {
587       TargetList Targets;
588 
589       for (auto Platform : Platforms) {
590         Platform = mapToPlatformType(Platform, Architectures.hasX86());
591 
592         for (const auto &&Architecture : Architectures) {
593           if ((Architecture == AK_i386) && (Platform == PLATFORM_MACCATALYST))
594             continue;
595 
596           Targets.emplace_back(Architecture, Platform);
597         }
598       }
599       return Targets;
600     }
601 
602     const InterfaceFile *denormalize(IO &IO) {
603       auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
604       assert(Ctx);
605 
606       auto *File = new InterfaceFile;
607       File->setPath(Ctx->Path);
608       File->setFileType(Ctx->FileKind);
609       File->addTargets(synthesizeTargets(Architectures, Platforms));
610       for (auto &ID : UUIDs)
611         File->addUUID(ID.first, ID.second);
612       File->setInstallName(InstallName);
613       File->setCurrentVersion(CurrentVersion);
614       File->setCompatibilityVersion(CompatibilityVersion);
615       File->setSwiftABIVersion(SwiftABIVersion);
616       File->setObjCConstraint(ObjCConstraint);
617       for (const auto &Target : File->targets())
618         File->addParentUmbrella(Target, ParentUmbrella);
619 
620       if (Ctx->FileKind == FileType::TBD_V1) {
621         File->setTwoLevelNamespace();
622         File->setApplicationExtensionSafe();
623       } else {
624         File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
625         File->setApplicationExtensionSafe(
626             !(Flags & TBDFlags::NotApplicationExtensionSafe));
627         File->setInstallAPI(Flags & TBDFlags::InstallAPI);
628       }
629 
630       for (const auto &Section : Exports) {
631         const auto Targets =
632             synthesizeTargets(Section.Architectures, Platforms);
633 
634         for (const auto &Lib : Section.AllowableClients)
635           for (const auto &Target : Targets)
636             File->addAllowableClient(Lib, Target);
637 
638         for (const auto &Lib : Section.ReexportedLibraries)
639           for (const auto &Target : Targets)
640             File->addReexportedLibrary(Lib, Target);
641 
642         for (const auto &Symbol : Section.Symbols) {
643           if (Ctx->FileKind != FileType::TBD_V3 &&
644               Symbol.value.startswith("_OBJC_EHTYPE_$_"))
645             File->addSymbol(SymbolKind::ObjectiveCClassEHType,
646                             Symbol.value.drop_front(15), Targets);
647           else
648             File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets);
649         }
650         for (auto &Symbol : Section.Classes) {
651           auto Name = Symbol.value;
652           if (Ctx->FileKind != FileType::TBD_V3)
653             Name = Name.drop_front();
654           File->addSymbol(SymbolKind::ObjectiveCClass, Name, Targets);
655         }
656         for (auto &Symbol : Section.ClassEHs)
657           File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol, Targets);
658         for (auto &Symbol : Section.IVars) {
659           auto Name = Symbol.value;
660           if (Ctx->FileKind != FileType::TBD_V3)
661             Name = Name.drop_front();
662           File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name,
663                           Targets);
664         }
665         for (auto &Symbol : Section.WeakDefSymbols)
666           File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
667                           SymbolFlags::WeakDefined);
668         for (auto &Symbol : Section.TLVSymbols)
669           File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
670                           SymbolFlags::ThreadLocalValue);
671       }
672 
673       for (const auto &Section : Undefineds) {
674         const auto Targets =
675             synthesizeTargets(Section.Architectures, Platforms);
676         for (auto &Symbol : Section.Symbols) {
677           if (Ctx->FileKind != FileType::TBD_V3 &&
678               Symbol.value.startswith("_OBJC_EHTYPE_$_"))
679             File->addSymbol(SymbolKind::ObjectiveCClassEHType,
680                             Symbol.value.drop_front(15), Targets,
681                             SymbolFlags::Undefined);
682           else
683             File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
684                             SymbolFlags::Undefined);
685         }
686         for (auto &Symbol : Section.Classes) {
687           auto Name = Symbol.value;
688           if (Ctx->FileKind != FileType::TBD_V3)
689             Name = Name.drop_front();
690           File->addSymbol(SymbolKind::ObjectiveCClass, Name, Targets,
691                           SymbolFlags::Undefined);
692         }
693         for (auto &Symbol : Section.ClassEHs)
694           File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol, Targets,
695                           SymbolFlags::Undefined);
696         for (auto &Symbol : Section.IVars) {
697           auto Name = Symbol.value;
698           if (Ctx->FileKind != FileType::TBD_V3)
699             Name = Name.drop_front();
700           File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name, Targets,
701                           SymbolFlags::Undefined);
702         }
703         for (auto &Symbol : Section.WeakRefSymbols)
704           File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
705                           SymbolFlags::Undefined | SymbolFlags::WeakReferenced);
706       }
707 
708       return File;
709     }
710 
711     llvm::BumpPtrAllocator Allocator;
712     StringRef copyString(StringRef String) {
713       if (String.empty())
714         return {};
715 
716       void *Ptr = Allocator.Allocate(String.size(), 1);
717       memcpy(Ptr, String.data(), String.size());
718       return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
719     }
720 
721     std::vector<Architecture> Architectures;
722     std::vector<UUID> UUIDs;
723     PlatformSet Platforms;
724     StringRef InstallName;
725     PackedVersion CurrentVersion;
726     PackedVersion CompatibilityVersion;
727     SwiftVersion SwiftABIVersion{0};
728     ObjCConstraintType ObjCConstraint{ObjCConstraintType::None};
729     TBDFlags Flags{TBDFlags::None};
730     StringRef ParentUmbrella;
731     std::vector<ExportSection> Exports;
732     std::vector<UndefinedSection> Undefineds;
733   };
734 
735   static void setFileTypeForInput(TextAPIContext *Ctx, IO &IO) {
736     if (IO.mapTag("!tapi-tbd", false))
737       Ctx->FileKind = FileType::TBD_V4;
738     else if (IO.mapTag("!tapi-tbd-v3", false))
739       Ctx->FileKind = FileType::TBD_V3;
740     else if (IO.mapTag("!tapi-tbd-v2", false))
741       Ctx->FileKind = FileType::TBD_V2;
742     else if (IO.mapTag("!tapi-tbd-v1", false) ||
743              IO.mapTag("tag:yaml.org,2002:map", false))
744       Ctx->FileKind = FileType::TBD_V1;
745     else {
746       Ctx->FileKind = FileType::Invalid;
747       return;
748     }
749   }
750 
751   static void mapping(IO &IO, const InterfaceFile *&File) {
752     auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
753     assert((!Ctx || !IO.outputting() ||
754             (Ctx && Ctx->FileKind != FileType::Invalid)) &&
755            "File type is not set in YAML context");
756 
757     if (!IO.outputting()) {
758       setFileTypeForInput(Ctx, IO);
759       switch (Ctx->FileKind) {
760       default:
761         break;
762       case FileType::TBD_V4:
763         mapKeysToValuesV4(IO, File);
764         return;
765       case FileType::Invalid:
766         IO.setError("unsupported file type");
767         return;
768       }
769     } else {
770       // Set file type when writing.
771       switch (Ctx->FileKind) {
772       default:
773         llvm_unreachable("unexpected file type");
774       case FileType::TBD_V4:
775         mapKeysToValuesV4(IO, File);
776         return;
777       case FileType::TBD_V3:
778         IO.mapTag("!tapi-tbd-v3", true);
779         break;
780       case FileType::TBD_V2:
781         IO.mapTag("!tapi-tbd-v2", true);
782         break;
783       case FileType::TBD_V1:
784         // Don't write the tag into the .tbd file for TBD v1
785         break;
786       }
787     }
788     mapKeysToValues(Ctx->FileKind, IO, File);
789   }
790 
791   using SectionList = std::vector<SymbolSection>;
792   struct NormalizedTBD_V4 {
793     explicit NormalizedTBD_V4(IO &IO) {}
794     NormalizedTBD_V4(IO &IO, const InterfaceFile *&File) {
795       auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
796       assert(Ctx);
797       TBDVersion = Ctx->FileKind >> 1;
798       Targets.insert(Targets.begin(), File->targets().begin(),
799                      File->targets().end());
800       for (const auto &IT : File->uuids())
801         UUIDs.emplace_back(IT.first, IT.second);
802       InstallName = File->getInstallName();
803       CurrentVersion = File->getCurrentVersion();
804       CompatibilityVersion = File->getCompatibilityVersion();
805       SwiftABIVersion = File->getSwiftABIVersion();
806 
807       Flags = TBDFlags::None;
808       if (!File->isApplicationExtensionSafe())
809         Flags |= TBDFlags::NotApplicationExtensionSafe;
810 
811       if (!File->isTwoLevelNamespace())
812         Flags |= TBDFlags::FlatNamespace;
813 
814       if (File->isInstallAPI())
815         Flags |= TBDFlags::InstallAPI;
816 
817       {
818         std::map<std::string, TargetList> valueToTargetList;
819         for (const auto &it : File->umbrellas())
820           valueToTargetList[it.second].emplace_back(it.first);
821 
822         for (const auto &it : valueToTargetList) {
823           UmbrellaSection CurrentSection;
824           CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
825                                         it.second.begin(), it.second.end());
826           CurrentSection.Umbrella = it.first;
827           ParentUmbrellas.emplace_back(std::move(CurrentSection));
828         }
829       }
830 
831       assignTargetsToLibrary(File->allowableClients(), AllowableClients);
832       assignTargetsToLibrary(File->reexportedLibraries(), ReexportedLibraries);
833 
834       auto handleSymbols =
835           [](SectionList &CurrentSections,
836              InterfaceFile::const_filtered_symbol_range Symbols,
837              std::function<bool(const Symbol *)> Pred) {
838             std::set<TargetList> TargetSet;
839             std::map<const Symbol *, TargetList> SymbolToTargetList;
840             for (const auto *Symbol : Symbols) {
841               if (!Pred(Symbol))
842                 continue;
843               TargetList Targets(Symbol->targets());
844               SymbolToTargetList[Symbol] = Targets;
845               TargetSet.emplace(std::move(Targets));
846             }
847             for (const auto &TargetIDs : TargetSet) {
848               SymbolSection CurrentSection;
849               CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
850                                             TargetIDs.begin(), TargetIDs.end());
851 
852               for (const auto &IT : SymbolToTargetList) {
853                 if (IT.second != TargetIDs)
854                   continue;
855 
856                 const auto *Symbol = IT.first;
857                 switch (Symbol->getKind()) {
858                 case SymbolKind::GlobalSymbol:
859                   if (Symbol->isWeakDefined())
860                     CurrentSection.WeakSymbols.emplace_back(Symbol->getName());
861                   else if (Symbol->isThreadLocalValue())
862                     CurrentSection.TlvSymbols.emplace_back(Symbol->getName());
863                   else
864                     CurrentSection.Symbols.emplace_back(Symbol->getName());
865                   break;
866                 case SymbolKind::ObjectiveCClass:
867                   CurrentSection.Classes.emplace_back(Symbol->getName());
868                   break;
869                 case SymbolKind::ObjectiveCClassEHType:
870                   CurrentSection.ClassEHs.emplace_back(Symbol->getName());
871                   break;
872                 case SymbolKind::ObjectiveCInstanceVariable:
873                   CurrentSection.Ivars.emplace_back(Symbol->getName());
874                   break;
875                 }
876               }
877               sort(CurrentSection.Symbols);
878               sort(CurrentSection.Classes);
879               sort(CurrentSection.ClassEHs);
880               sort(CurrentSection.Ivars);
881               sort(CurrentSection.WeakSymbols);
882               sort(CurrentSection.TlvSymbols);
883               CurrentSections.emplace_back(std::move(CurrentSection));
884             }
885           };
886 
887       handleSymbols(Exports, File->exports(), [](const Symbol *Symbol) {
888         return !Symbol->isReexported();
889       });
890       handleSymbols(Reexports, File->exports(), [](const Symbol *Symbol) {
891         return Symbol->isReexported();
892       });
893       handleSymbols(Undefineds, File->undefineds(),
894                     [](const Symbol *Symbol) { return true; });
895     }
896 
897     const InterfaceFile *denormalize(IO &IO) {
898       auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
899       assert(Ctx);
900 
901       auto *File = new InterfaceFile;
902       File->setPath(Ctx->Path);
903       File->setFileType(Ctx->FileKind);
904       for (auto &id : UUIDs)
905         File->addUUID(id.TargetID, id.Value);
906       File->addTargets(Targets);
907       File->setInstallName(InstallName);
908       File->setCurrentVersion(CurrentVersion);
909       File->setCompatibilityVersion(CompatibilityVersion);
910       File->setSwiftABIVersion(SwiftABIVersion);
911       for (const auto &CurrentSection : ParentUmbrellas)
912         for (const auto &target : CurrentSection.Targets)
913           File->addParentUmbrella(target, CurrentSection.Umbrella);
914       File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
915       File->setApplicationExtensionSafe(
916           !(Flags & TBDFlags::NotApplicationExtensionSafe));
917       File->setInstallAPI(Flags & TBDFlags::InstallAPI);
918 
919       for (const auto &CurrentSection : AllowableClients) {
920         for (const auto &lib : CurrentSection.Values)
921           for (const auto &Target : CurrentSection.Targets)
922             File->addAllowableClient(lib, Target);
923       }
924 
925       for (const auto &CurrentSection : ReexportedLibraries) {
926         for (const auto &Lib : CurrentSection.Values)
927           for (const auto &Target : CurrentSection.Targets)
928             File->addReexportedLibrary(Lib, Target);
929       }
930 
931       auto handleSymbols = [File](const SectionList &CurrentSections,
932                                   SymbolFlags Flag = SymbolFlags::None) {
933         for (const auto &CurrentSection : CurrentSections) {
934           for (auto &sym : CurrentSection.Symbols)
935             File->addSymbol(SymbolKind::GlobalSymbol, sym,
936                             CurrentSection.Targets, Flag);
937 
938           for (auto &sym : CurrentSection.Classes)
939             File->addSymbol(SymbolKind::ObjectiveCClass, sym,
940                             CurrentSection.Targets);
941 
942           for (auto &sym : CurrentSection.ClassEHs)
943             File->addSymbol(SymbolKind::ObjectiveCClassEHType, sym,
944                             CurrentSection.Targets);
945 
946           for (auto &sym : CurrentSection.Ivars)
947             File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, sym,
948                             CurrentSection.Targets);
949 
950           for (auto &sym : CurrentSection.WeakSymbols)
951             File->addSymbol(SymbolKind::GlobalSymbol, sym,
952                             CurrentSection.Targets, SymbolFlags::WeakDefined);
953 
954           for (auto &sym : CurrentSection.TlvSymbols)
955             File->addSymbol(SymbolKind::GlobalSymbol, sym,
956                             CurrentSection.Targets,
957                             SymbolFlags::ThreadLocalValue);
958         }
959       };
960 
961       handleSymbols(Exports);
962       handleSymbols(Reexports, SymbolFlags::Rexported);
963       handleSymbols(Undefineds, SymbolFlags::Undefined);
964 
965       return File;
966     }
967 
968     unsigned TBDVersion;
969     std::vector<UUIDv4> UUIDs;
970     TargetList Targets;
971     StringRef InstallName;
972     PackedVersion CurrentVersion;
973     PackedVersion CompatibilityVersion;
974     SwiftVersion SwiftABIVersion{0};
975     std::vector<MetadataSection> AllowableClients;
976     std::vector<MetadataSection> ReexportedLibraries;
977     TBDFlags Flags{TBDFlags::None};
978     std::vector<UmbrellaSection> ParentUmbrellas;
979     SectionList Exports;
980     SectionList Reexports;
981     SectionList Undefineds;
982 
983   private:
984     void assignTargetsToLibrary(const std::vector<InterfaceFileRef> &Libraries,
985                                 std::vector<MetadataSection> &Section) {
986       std::set<TargetList> targetSet;
987       std::map<const InterfaceFileRef *, TargetList> valueToTargetList;
988       for (const auto &library : Libraries) {
989         TargetList targets(library.targets());
990         valueToTargetList[&library] = targets;
991         targetSet.emplace(std::move(targets));
992       }
993 
994       for (const auto &targets : targetSet) {
995         MetadataSection CurrentSection;
996         CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
997                                       targets.begin(), targets.end());
998 
999         for (const auto &it : valueToTargetList) {
1000           if (it.second != targets)
1001             continue;
1002 
1003           CurrentSection.Values.emplace_back(it.first->getInstallName());
1004         }
1005         llvm::sort(CurrentSection.Values);
1006         Section.emplace_back(std::move(CurrentSection));
1007       }
1008     }
1009   };
1010 
1011   static void mapKeysToValues(FileType FileKind, IO &IO,
1012                               const InterfaceFile *&File) {
1013     MappingNormalization<NormalizedTBD, const InterfaceFile *> Keys(IO, File);
1014     IO.mapRequired("archs", Keys->Architectures);
1015     if (FileKind != FileType::TBD_V1)
1016       IO.mapOptional("uuids", Keys->UUIDs);
1017     IO.mapRequired("platform", Keys->Platforms);
1018     if (FileKind != FileType::TBD_V1)
1019       IO.mapOptional("flags", Keys->Flags, TBDFlags::None);
1020     IO.mapRequired("install-name", Keys->InstallName);
1021     IO.mapOptional("current-version", Keys->CurrentVersion,
1022                    PackedVersion(1, 0, 0));
1023     IO.mapOptional("compatibility-version", Keys->CompatibilityVersion,
1024                    PackedVersion(1, 0, 0));
1025     if (FileKind != FileType::TBD_V3)
1026       IO.mapOptional("swift-version", Keys->SwiftABIVersion, SwiftVersion(0));
1027     else
1028       IO.mapOptional("swift-abi-version", Keys->SwiftABIVersion,
1029                      SwiftVersion(0));
1030     IO.mapOptional("objc-constraint", Keys->ObjCConstraint,
1031                    (FileKind == FileType::TBD_V1)
1032                        ? ObjCConstraintType::None
1033                        : ObjCConstraintType::Retain_Release);
1034     if (FileKind != FileType::TBD_V1)
1035       IO.mapOptional("parent-umbrella", Keys->ParentUmbrella, StringRef());
1036     IO.mapOptional("exports", Keys->Exports);
1037     if (FileKind != FileType::TBD_V1)
1038       IO.mapOptional("undefineds", Keys->Undefineds);
1039   }
1040 
1041   static void mapKeysToValuesV4(IO &IO, const InterfaceFile *&File) {
1042     MappingNormalization<NormalizedTBD_V4, const InterfaceFile *> Keys(IO,
1043                                                                        File);
1044     IO.mapTag("!tapi-tbd", true);
1045     IO.mapRequired("tbd-version", Keys->TBDVersion);
1046     IO.mapRequired("targets", Keys->Targets);
1047     IO.mapOptional("uuids", Keys->UUIDs);
1048     IO.mapOptional("flags", Keys->Flags, TBDFlags::None);
1049     IO.mapRequired("install-name", Keys->InstallName);
1050     IO.mapOptional("current-version", Keys->CurrentVersion,
1051                    PackedVersion(1, 0, 0));
1052     IO.mapOptional("compatibility-version", Keys->CompatibilityVersion,
1053                    PackedVersion(1, 0, 0));
1054     IO.mapOptional("swift-abi-version", Keys->SwiftABIVersion, SwiftVersion(0));
1055     IO.mapOptional("parent-umbrella", Keys->ParentUmbrellas);
1056     auto OptionKind = MetadataSection::Option::Clients;
1057     IO.mapOptionalWithContext("allowable-clients", Keys->AllowableClients,
1058                               OptionKind);
1059     OptionKind = MetadataSection::Option::Libraries;
1060     IO.mapOptionalWithContext("reexported-libraries", Keys->ReexportedLibraries,
1061                               OptionKind);
1062     IO.mapOptional("exports", Keys->Exports);
1063     IO.mapOptional("reexports", Keys->Reexports);
1064     IO.mapOptional("undefineds", Keys->Undefineds);
1065   }
1066 };
1067 
1068 template <>
1069 struct DocumentListTraits<std::vector<const MachO::InterfaceFile *>> {
1070   static size_t size(IO &IO, std::vector<const MachO::InterfaceFile *> &Seq) {
1071     return Seq.size();
1072   }
1073   static const InterfaceFile *&
1074   element(IO &IO, std::vector<const InterfaceFile *> &Seq, size_t Index) {
1075     if (Index >= Seq.size())
1076       Seq.resize(Index + 1);
1077     return Seq[Index];
1078   }
1079 };
1080 
1081 } // end namespace yaml.
1082 } // namespace llvm
1083 
1084 static void DiagHandler(const SMDiagnostic &Diag, void *Context) {
1085   auto *File = static_cast<TextAPIContext *>(Context);
1086   SmallString<1024> Message;
1087   raw_svector_ostream S(Message);
1088 
1089   SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), File->Path,
1090                        Diag.getLineNo(), Diag.getColumnNo(), Diag.getKind(),
1091                        Diag.getMessage(), Diag.getLineContents(),
1092                        Diag.getRanges(), Diag.getFixIts());
1093 
1094   NewDiag.print(nullptr, S);
1095   File->ErrorMessage = ("malformed file\n" + Message).str();
1096 }
1097 
1098 namespace {
1099 
1100 Expected<FileType> canReadFileType(MemoryBufferRef InputBuffer) {
1101   auto TAPIFile = InputBuffer.getBuffer().trim();
1102   if (TAPIFile.startswith("{") && TAPIFile.endswith("}"))
1103     return FileType::TBD_V5;
1104 
1105   if (!TAPIFile.endswith("..."))
1106     return createStringError(std::errc::not_supported, "unsupported file type");
1107 
1108   if (TAPIFile.startswith("--- !tapi-tbd\n"))
1109     return FileType::TBD_V4;
1110 
1111   if (TAPIFile.startswith("--- !tapi-tbd-v3\n"))
1112     return FileType::TBD_V3;
1113 
1114   if (TAPIFile.startswith("--- !tapi-tbd-v2\n"))
1115     return FileType::TBD_V2;
1116 
1117   if (TAPIFile.startswith("--- !tapi-tbd-v1\n") ||
1118       TAPIFile.startswith("---\narchs:"))
1119     return FileType::TBD_V1;
1120 
1121   return createStringError(std::errc::not_supported, "unsupported file type");
1122 }
1123 } // namespace
1124 
1125 Expected<std::unique_ptr<InterfaceFile>>
1126 TextAPIReader::get(MemoryBufferRef InputBuffer) {
1127   TextAPIContext Ctx;
1128   Ctx.Path = std::string(InputBuffer.getBufferIdentifier());
1129   if (auto FTOrErr = canReadFileType(InputBuffer))
1130     Ctx.FileKind = *FTOrErr;
1131   else
1132     return FTOrErr.takeError();
1133 
1134   // Handle JSON Format.
1135   if (Ctx.FileKind >= FileType::TBD_V5) {
1136     auto FileOrErr = getInterfaceFileFromJSON(InputBuffer.getBuffer());
1137     if (!FileOrErr)
1138       return FileOrErr.takeError();
1139     return std::move(*FileOrErr);
1140   }
1141   yaml::Input YAMLIn(InputBuffer.getBuffer(), &Ctx, DiagHandler, &Ctx);
1142 
1143   // Fill vector with interface file objects created by parsing the YAML file.
1144   std::vector<const InterfaceFile *> Files;
1145   YAMLIn >> Files;
1146 
1147   // YAMLIn dynamically allocates for Interface file and in case of error,
1148   // memory leak will occur unless wrapped around unique_ptr
1149   auto File = std::unique_ptr<InterfaceFile>(
1150       const_cast<InterfaceFile *>(Files.front()));
1151 
1152   for (const InterfaceFile *FI : llvm::drop_begin(Files))
1153     File->addDocument(
1154         std::shared_ptr<InterfaceFile>(const_cast<InterfaceFile *>(FI)));
1155 
1156   if (YAMLIn.error())
1157     return make_error<StringError>(Ctx.ErrorMessage, YAMLIn.error());
1158 
1159   return std::move(File);
1160 }
1161 
1162 Error TextAPIWriter::writeToStream(raw_ostream &OS, const InterfaceFile &File) {
1163   TextAPIContext Ctx;
1164   Ctx.Path = std::string(File.getPath());
1165   Ctx.FileKind = File.getFileType();
1166   llvm::yaml::Output YAMLOut(OS, &Ctx, /*WrapColumn=*/80);
1167 
1168   std::vector<const InterfaceFile *> Files;
1169   Files.emplace_back(&File);
1170 
1171   for (auto Document : File.documents())
1172     Files.emplace_back(Document.get());
1173 
1174   // Stream out yaml.
1175   YAMLOut << Files;
1176 
1177   return Error::success();
1178 }
1179