xref: /aosp_15_r20/external/swiftshader/third_party/llvm-10.0/llvm/lib/TextAPI/MachO/TextStub.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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/MachO/Architecture.h"
23 #include "llvm/TextAPI/MachO/ArchitectureSet.h"
24 #include "llvm/TextAPI/MachO/InterfaceFile.h"
25 #include "llvm/TextAPI/MachO/PackedVersion.h"
26 #include "llvm/TextAPI/MachO/TextAPIReader.h"
27 #include "llvm/TextAPI/MachO/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;
UUIDv4__anon98dd83b20111::UUIDv4258   UUIDv4(const Target &TargetID, const std::string &Value)
259       : TargetID(TargetID), Value(Value) {}
260 };
261 
262 // clang-format off
263 enum TBDFlags : unsigned {
264   None                         = 0U,
265   FlatNamespace                = 1U << 0,
266   NotApplicationExtensionSafe  = 1U << 1,
267   InstallAPI                   = 1U << 2,
268   LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/InstallAPI),
269 };
270 // clang-format on
271 } // end anonymous namespace.
272 
273 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(Architecture)
274 LLVM_YAML_IS_SEQUENCE_VECTOR(ExportSection)
275 LLVM_YAML_IS_SEQUENCE_VECTOR(UndefinedSection)
276 // Specific to TBDv4
277 LLVM_YAML_IS_SEQUENCE_VECTOR(SymbolSection)
278 LLVM_YAML_IS_SEQUENCE_VECTOR(MetadataSection)
279 LLVM_YAML_IS_SEQUENCE_VECTOR(UmbrellaSection)
280 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(Target)
281 LLVM_YAML_IS_SEQUENCE_VECTOR(UUIDv4)
282 
283 namespace llvm {
284 namespace yaml {
285 
286 template <> struct MappingTraits<ExportSection> {
mappingllvm::yaml::MappingTraits287   static void mapping(IO &IO, ExportSection &Section) {
288     const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
289     assert((!Ctx || (Ctx && Ctx->FileKind != FileType::Invalid)) &&
290            "File type is not set in YAML context");
291 
292     IO.mapRequired("archs", Section.Architectures);
293     if (Ctx->FileKind == FileType::TBD_V1)
294       IO.mapOptional("allowed-clients", Section.AllowableClients);
295     else
296       IO.mapOptional("allowable-clients", Section.AllowableClients);
297     IO.mapOptional("re-exports", Section.ReexportedLibraries);
298     IO.mapOptional("symbols", Section.Symbols);
299     IO.mapOptional("objc-classes", Section.Classes);
300     if (Ctx->FileKind == FileType::TBD_V3)
301       IO.mapOptional("objc-eh-types", Section.ClassEHs);
302     IO.mapOptional("objc-ivars", Section.IVars);
303     IO.mapOptional("weak-def-symbols", Section.WeakDefSymbols);
304     IO.mapOptional("thread-local-symbols", Section.TLVSymbols);
305   }
306 };
307 
308 template <> struct MappingTraits<UndefinedSection> {
mappingllvm::yaml::MappingTraits309   static void mapping(IO &IO, UndefinedSection &Section) {
310     const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
311     assert((!Ctx || (Ctx && Ctx->FileKind != FileType::Invalid)) &&
312            "File type is not set in YAML context");
313 
314     IO.mapRequired("archs", Section.Architectures);
315     IO.mapOptional("symbols", Section.Symbols);
316     IO.mapOptional("objc-classes", Section.Classes);
317     if (Ctx->FileKind == FileType::TBD_V3)
318       IO.mapOptional("objc-eh-types", Section.ClassEHs);
319     IO.mapOptional("objc-ivars", Section.IVars);
320     IO.mapOptional("weak-ref-symbols", Section.WeakRefSymbols);
321   }
322 };
323 
324 template <> struct MappingTraits<SymbolSection> {
mappingllvm::yaml::MappingTraits325   static void mapping(IO &IO, SymbolSection &Section) {
326     IO.mapRequired("targets", Section.Targets);
327     IO.mapOptional("symbols", Section.Symbols);
328     IO.mapOptional("objc-classes", Section.Classes);
329     IO.mapOptional("objc-eh-types", Section.ClassEHs);
330     IO.mapOptional("objc-ivars", Section.Ivars);
331     IO.mapOptional("weak-symbols", Section.WeakSymbols);
332     IO.mapOptional("thread-local-symbols", Section.TlvSymbols);
333   }
334 };
335 
336 template <> struct MappingTraits<UmbrellaSection> {
mappingllvm::yaml::MappingTraits337   static void mapping(IO &IO, UmbrellaSection &Section) {
338     IO.mapRequired("targets", Section.Targets);
339     IO.mapRequired("umbrella", Section.Umbrella);
340   }
341 };
342 
343 template <> struct MappingTraits<UUIDv4> {
mappingllvm::yaml::MappingTraits344   static void mapping(IO &IO, UUIDv4 &UUID) {
345     IO.mapRequired("target", UUID.TargetID);
346     IO.mapRequired("value", UUID.Value);
347   }
348 };
349 
350 template <>
351 struct MappingContextTraits<MetadataSection, MetadataSection::Option> {
mappingllvm::yaml::MappingContextTraits352   static void mapping(IO &IO, MetadataSection &Section,
353                       MetadataSection::Option &OptionKind) {
354     IO.mapRequired("targets", Section.Targets);
355     switch (OptionKind) {
356     case MetadataSection::Option::Clients:
357       IO.mapRequired("clients", Section.Values);
358       return;
359     case MetadataSection::Option::Libraries:
360       IO.mapRequired("libraries", Section.Values);
361       return;
362     }
363     llvm_unreachable("unexpected option for metadata");
364   }
365 };
366 
367 template <> struct ScalarBitSetTraits<TBDFlags> {
bitsetllvm::yaml::ScalarBitSetTraits368   static void bitset(IO &IO, TBDFlags &Flags) {
369     IO.bitSetCase(Flags, "flat_namespace", TBDFlags::FlatNamespace);
370     IO.bitSetCase(Flags, "not_app_extension_safe",
371                   TBDFlags::NotApplicationExtensionSafe);
372     IO.bitSetCase(Flags, "installapi", TBDFlags::InstallAPI);
373   }
374 };
375 
376 template <> struct ScalarTraits<Target> {
outputllvm::yaml::ScalarTraits377   static void output(const Target &Value, void *, raw_ostream &OS) {
378     OS << Value.Arch << "-";
379     switch (Value.Platform) {
380     default:
381       OS << "unknown";
382       break;
383     case PlatformKind::macOS:
384       OS << "macos";
385       break;
386     case PlatformKind::iOS:
387       OS << "ios";
388       break;
389     case PlatformKind::tvOS:
390       OS << "tvos";
391       break;
392     case PlatformKind::watchOS:
393       OS << "watchos";
394       break;
395     case PlatformKind::bridgeOS:
396       OS << "bridgeos";
397       break;
398     case PlatformKind::macCatalyst:
399       OS << "maccatalyst";
400       break;
401     case PlatformKind::iOSSimulator:
402       OS << "ios-simulator";
403       break;
404     case PlatformKind::tvOSSimulator:
405       OS << "tvos-simulator";
406       break;
407     case PlatformKind::watchOSSimulator:
408       OS << "watchos-simulator";
409       break;
410     }
411   }
412 
inputllvm::yaml::ScalarTraits413   static StringRef input(StringRef Scalar, void *, Target &Value) {
414     auto Result = Target::create(Scalar);
415     if (!Result)
416       return toString(Result.takeError());
417 
418     Value = *Result;
419     if (Value.Arch == AK_unknown)
420       return "unknown architecture";
421     if (Value.Platform == PlatformKind::unknown)
422       return "unknown platform";
423 
424     return {};
425   }
426 
mustQuotellvm::yaml::ScalarTraits427   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
428 };
429 
430 template <> struct MappingTraits<const InterfaceFile *> {
431   struct NormalizedTBD {
NormalizedTBDllvm::yaml::MappingTraits::NormalizedTBD432     explicit NormalizedTBD(IO &IO) {}
NormalizedTBDllvm::yaml::MappingTraits::NormalizedTBD433     NormalizedTBD(IO &IO, const InterfaceFile *&File) {
434       Architectures = File->getArchitectures();
435       UUIDs = File->uuids();
436       Platforms = File->getPlatforms();
437       InstallName = File->getInstallName();
438       CurrentVersion = PackedVersion(File->getCurrentVersion());
439       CompatibilityVersion = PackedVersion(File->getCompatibilityVersion());
440       SwiftABIVersion = File->getSwiftABIVersion();
441       ObjCConstraint = File->getObjCConstraint();
442 
443       Flags = TBDFlags::None;
444       if (!File->isApplicationExtensionSafe())
445         Flags |= TBDFlags::NotApplicationExtensionSafe;
446 
447       if (!File->isTwoLevelNamespace())
448         Flags |= TBDFlags::FlatNamespace;
449 
450       if (File->isInstallAPI())
451         Flags |= TBDFlags::InstallAPI;
452 
453       for (const auto &Iter : File->umbrellas()) {
454         ParentUmbrella = Iter.second;
455         break;
456       }
457 
458       std::set<ArchitectureSet> ArchSet;
459       for (const auto &Library : File->allowableClients())
460         ArchSet.insert(Library.getArchitectures());
461 
462       for (const auto &Library : File->reexportedLibraries())
463         ArchSet.insert(Library.getArchitectures());
464 
465       std::map<const Symbol *, ArchitectureSet> SymbolToArchSet;
466       for (const auto *Symbol : File->exports()) {
467         auto Architectures = Symbol->getArchitectures();
468         SymbolToArchSet[Symbol] = Architectures;
469         ArchSet.insert(Architectures);
470       }
471 
472       for (auto Architectures : ArchSet) {
473         ExportSection Section;
474         Section.Architectures = Architectures;
475 
476         for (const auto &Library : File->allowableClients())
477           if (Library.getArchitectures() == Architectures)
478             Section.AllowableClients.emplace_back(Library.getInstallName());
479 
480         for (const auto &Library : File->reexportedLibraries())
481           if (Library.getArchitectures() == Architectures)
482             Section.ReexportedLibraries.emplace_back(Library.getInstallName());
483 
484         for (const auto &SymArch : SymbolToArchSet) {
485           if (SymArch.second != Architectures)
486             continue;
487 
488           const auto *Symbol = SymArch.first;
489           switch (Symbol->getKind()) {
490           case SymbolKind::GlobalSymbol:
491             if (Symbol->isWeakDefined())
492               Section.WeakDefSymbols.emplace_back(Symbol->getName());
493             else if (Symbol->isThreadLocalValue())
494               Section.TLVSymbols.emplace_back(Symbol->getName());
495             else
496               Section.Symbols.emplace_back(Symbol->getName());
497             break;
498           case SymbolKind::ObjectiveCClass:
499             if (File->getFileType() != FileType::TBD_V3)
500               Section.Classes.emplace_back(
501                   copyString("_" + Symbol->getName().str()));
502             else
503               Section.Classes.emplace_back(Symbol->getName());
504             break;
505           case SymbolKind::ObjectiveCClassEHType:
506             if (File->getFileType() != FileType::TBD_V3)
507               Section.Symbols.emplace_back(
508                   copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str()));
509             else
510               Section.ClassEHs.emplace_back(Symbol->getName());
511             break;
512           case SymbolKind::ObjectiveCInstanceVariable:
513             if (File->getFileType() != FileType::TBD_V3)
514               Section.IVars.emplace_back(
515                   copyString("_" + Symbol->getName().str()));
516             else
517               Section.IVars.emplace_back(Symbol->getName());
518             break;
519           }
520         }
521         llvm::sort(Section.Symbols.begin(), Section.Symbols.end());
522         llvm::sort(Section.Classes.begin(), Section.Classes.end());
523         llvm::sort(Section.ClassEHs.begin(), Section.ClassEHs.end());
524         llvm::sort(Section.IVars.begin(), Section.IVars.end());
525         llvm::sort(Section.WeakDefSymbols.begin(),
526                    Section.WeakDefSymbols.end());
527         llvm::sort(Section.TLVSymbols.begin(), Section.TLVSymbols.end());
528         Exports.emplace_back(std::move(Section));
529       }
530 
531       ArchSet.clear();
532       SymbolToArchSet.clear();
533 
534       for (const auto *Symbol : File->undefineds()) {
535         auto Architectures = Symbol->getArchitectures();
536         SymbolToArchSet[Symbol] = Architectures;
537         ArchSet.insert(Architectures);
538       }
539 
540       for (auto Architectures : ArchSet) {
541         UndefinedSection Section;
542         Section.Architectures = Architectures;
543 
544         for (const auto &SymArch : SymbolToArchSet) {
545           if (SymArch.second != Architectures)
546             continue;
547 
548           const auto *Symbol = SymArch.first;
549           switch (Symbol->getKind()) {
550           case SymbolKind::GlobalSymbol:
551             if (Symbol->isWeakReferenced())
552               Section.WeakRefSymbols.emplace_back(Symbol->getName());
553             else
554               Section.Symbols.emplace_back(Symbol->getName());
555             break;
556           case SymbolKind::ObjectiveCClass:
557             if (File->getFileType() != FileType::TBD_V3)
558               Section.Classes.emplace_back(
559                   copyString("_" + Symbol->getName().str()));
560             else
561               Section.Classes.emplace_back(Symbol->getName());
562             break;
563           case SymbolKind::ObjectiveCClassEHType:
564             if (File->getFileType() != FileType::TBD_V3)
565               Section.Symbols.emplace_back(
566                   copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str()));
567             else
568               Section.ClassEHs.emplace_back(Symbol->getName());
569             break;
570           case SymbolKind::ObjectiveCInstanceVariable:
571             if (File->getFileType() != FileType::TBD_V3)
572               Section.IVars.emplace_back(
573                   copyString("_" + Symbol->getName().str()));
574             else
575               Section.IVars.emplace_back(Symbol->getName());
576             break;
577           }
578         }
579         llvm::sort(Section.Symbols.begin(), Section.Symbols.end());
580         llvm::sort(Section.Classes.begin(), Section.Classes.end());
581         llvm::sort(Section.ClassEHs.begin(), Section.ClassEHs.end());
582         llvm::sort(Section.IVars.begin(), Section.IVars.end());
583         llvm::sort(Section.WeakRefSymbols.begin(),
584                    Section.WeakRefSymbols.end());
585         Undefineds.emplace_back(std::move(Section));
586       }
587     }
588 
589     // TBD v1 - TBD v3 files only support one platform and several
590     // architectures. It is possible to have more than one platform for TBD v3
591     // files, but the architectures don't apply to all
592     // platforms, specifically to filter out the i386 slice from
593     // platform macCatalyst.
synthesizeTargetsllvm::yaml::MappingTraits::NormalizedTBD594     TargetList synthesizeTargets(ArchitectureSet Architectures,
595                                           const PlatformSet &Platforms) {
596       TargetList Targets;
597 
598       for (auto Platform : Platforms) {
599         Platform = mapToPlatformKind(Platform, Architectures.hasX86());
600 
601         for (const auto &&Architecture : Architectures) {
602           if ((Architecture == AK_i386) &&
603               (Platform == PlatformKind::macCatalyst))
604             continue;
605 
606           Targets.emplace_back(Architecture, Platform);
607         }
608       }
609       return Targets;
610     }
611 
denormalizellvm::yaml::MappingTraits::NormalizedTBD612     const InterfaceFile *denormalize(IO &IO) {
613       auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
614       assert(Ctx);
615 
616       auto *File = new InterfaceFile;
617       File->setPath(Ctx->Path);
618       File->setFileType(Ctx->FileKind);
619       File->addTargets(synthesizeTargets(Architectures, Platforms));
620       for (auto &ID : UUIDs)
621         File->addUUID(ID.first, ID.second);
622       File->setInstallName(InstallName);
623       File->setCurrentVersion(CurrentVersion);
624       File->setCompatibilityVersion(CompatibilityVersion);
625       File->setSwiftABIVersion(SwiftABIVersion);
626       File->setObjCConstraint(ObjCConstraint);
627       for (const auto &Target : File->targets())
628         File->addParentUmbrella(Target, ParentUmbrella);
629 
630       if (Ctx->FileKind == FileType::TBD_V1) {
631         File->setTwoLevelNamespace();
632         File->setApplicationExtensionSafe();
633       } else {
634         File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
635         File->setApplicationExtensionSafe(
636             !(Flags & TBDFlags::NotApplicationExtensionSafe));
637         File->setInstallAPI(Flags & TBDFlags::InstallAPI);
638       }
639 
640       for (const auto &Section : Exports) {
641         const auto Targets =
642             synthesizeTargets(Section.Architectures, Platforms);
643 
644         for (const auto &Lib : Section.AllowableClients)
645           for (const auto &Target : Targets)
646             File->addAllowableClient(Lib, Target);
647 
648         for (const auto &Lib : Section.ReexportedLibraries)
649           for (const auto &Target : Targets)
650             File->addReexportedLibrary(Lib, Target);
651 
652         for (const auto &Symbol : Section.Symbols) {
653           if (Ctx->FileKind != FileType::TBD_V3 &&
654               Symbol.value.startswith("_OBJC_EHTYPE_$_"))
655             File->addSymbol(SymbolKind::ObjectiveCClassEHType,
656                             Symbol.value.drop_front(15), Targets);
657           else
658             File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets);
659         }
660         for (auto &Symbol : Section.Classes) {
661           auto Name = Symbol.value;
662           if (Ctx->FileKind != FileType::TBD_V3)
663             Name = Name.drop_front();
664           File->addSymbol(SymbolKind::ObjectiveCClass, Name, Targets);
665         }
666         for (auto &Symbol : Section.ClassEHs)
667           File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol, Targets);
668         for (auto &Symbol : Section.IVars) {
669           auto Name = Symbol.value;
670           if (Ctx->FileKind != FileType::TBD_V3)
671             Name = Name.drop_front();
672           File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name,
673                           Targets);
674         }
675         for (auto &Symbol : Section.WeakDefSymbols)
676           File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
677                           SymbolFlags::WeakDefined);
678         for (auto &Symbol : Section.TLVSymbols)
679           File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
680                           SymbolFlags::ThreadLocalValue);
681       }
682 
683       for (const auto &Section : Undefineds) {
684         const auto Targets =
685             synthesizeTargets(Section.Architectures, Platforms);
686         for (auto &Symbol : Section.Symbols) {
687           if (Ctx->FileKind != FileType::TBD_V3 &&
688               Symbol.value.startswith("_OBJC_EHTYPE_$_"))
689             File->addSymbol(SymbolKind::ObjectiveCClassEHType,
690                             Symbol.value.drop_front(15), Targets,
691                             SymbolFlags::Undefined);
692           else
693             File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
694                             SymbolFlags::Undefined);
695         }
696         for (auto &Symbol : Section.Classes) {
697           auto Name = Symbol.value;
698           if (Ctx->FileKind != FileType::TBD_V3)
699             Name = Name.drop_front();
700           File->addSymbol(SymbolKind::ObjectiveCClass, Name, Targets,
701                           SymbolFlags::Undefined);
702         }
703         for (auto &Symbol : Section.ClassEHs)
704           File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol, Targets,
705                           SymbolFlags::Undefined);
706         for (auto &Symbol : Section.IVars) {
707           auto Name = Symbol.value;
708           if (Ctx->FileKind != FileType::TBD_V3)
709             Name = Name.drop_front();
710           File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name, Targets,
711                           SymbolFlags::Undefined);
712         }
713         for (auto &Symbol : Section.WeakRefSymbols)
714           File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
715                           SymbolFlags::Undefined | SymbolFlags::WeakReferenced);
716       }
717 
718       return File;
719     }
720 
721     llvm::BumpPtrAllocator Allocator;
copyStringllvm::yaml::MappingTraits::NormalizedTBD722     StringRef copyString(StringRef String) {
723       if (String.empty())
724         return {};
725 
726       void *Ptr = Allocator.Allocate(String.size(), 1);
727       memcpy(Ptr, String.data(), String.size());
728       return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
729     }
730 
731     std::vector<Architecture> Architectures;
732     std::vector<UUID> UUIDs;
733     PlatformSet Platforms;
734     StringRef InstallName;
735     PackedVersion CurrentVersion;
736     PackedVersion CompatibilityVersion;
737     SwiftVersion SwiftABIVersion{0};
738     ObjCConstraintType ObjCConstraint{ObjCConstraintType::None};
739     TBDFlags Flags{TBDFlags::None};
740     StringRef ParentUmbrella;
741     std::vector<ExportSection> Exports;
742     std::vector<UndefinedSection> Undefineds;
743   };
744 
setFileTypeForInputllvm::yaml::MappingTraits745   static void setFileTypeForInput(TextAPIContext *Ctx, IO &IO) {
746     if (IO.mapTag("!tapi-tbd", false))
747       Ctx->FileKind = FileType::TBD_V4;
748     else if (IO.mapTag("!tapi-tbd-v3", false))
749       Ctx->FileKind = FileType::TBD_V3;
750     else if (IO.mapTag("!tapi-tbd-v2", false))
751       Ctx->FileKind = FileType::TBD_V2;
752     else if (IO.mapTag("!tapi-tbd-v1", false) ||
753              IO.mapTag("tag:yaml.org,2002:map", false))
754       Ctx->FileKind = FileType::TBD_V1;
755     else {
756       Ctx->FileKind = FileType::Invalid;
757       return;
758     }
759   }
760 
mappingllvm::yaml::MappingTraits761   static void mapping(IO &IO, const InterfaceFile *&File) {
762     auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
763     assert((!Ctx || !IO.outputting() ||
764             (Ctx && Ctx->FileKind != FileType::Invalid)) &&
765            "File type is not set in YAML context");
766 
767     if (!IO.outputting()) {
768       setFileTypeForInput(Ctx, IO);
769       switch (Ctx->FileKind) {
770       default:
771         break;
772       case FileType::TBD_V4:
773         mapKeysToValuesV4(IO, File);
774         return;
775       case FileType::Invalid:
776         IO.setError("unsupported file type");
777         return;
778       }
779     } else {
780       // Set file type when writing.
781       switch (Ctx->FileKind) {
782       default:
783         llvm_unreachable("unexpected file type");
784       case FileType::TBD_V4:
785         mapKeysToValuesV4(IO, File);
786         return;
787       case FileType::TBD_V3:
788         IO.mapTag("!tapi-tbd-v3", true);
789         break;
790       case FileType::TBD_V2:
791         IO.mapTag("!tapi-tbd-v2", true);
792         break;
793       case FileType::TBD_V1:
794         // Don't write the tag into the .tbd file for TBD v1
795         break;
796       }
797     }
798     mapKeysToValues(Ctx->FileKind, IO, File);
799   }
800 
801   using SectionList = std::vector<SymbolSection>;
802   struct NormalizedTBD_V4 {
NormalizedTBD_V4llvm::yaml::MappingTraits::NormalizedTBD_V4803     explicit NormalizedTBD_V4(IO &IO) {}
NormalizedTBD_V4llvm::yaml::MappingTraits::NormalizedTBD_V4804     NormalizedTBD_V4(IO &IO, const InterfaceFile *&File) {
805       auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
806       assert(Ctx);
807       TBDVersion = Ctx->FileKind >> 1;
808       Targets.insert(Targets.begin(), File->targets().begin(),
809                      File->targets().end());
810       for (const auto &IT : File->uuids())
811         UUIDs.emplace_back(IT.first, IT.second);
812       InstallName = File->getInstallName();
813       CurrentVersion = File->getCurrentVersion();
814       CompatibilityVersion = File->getCompatibilityVersion();
815       SwiftABIVersion = File->getSwiftABIVersion();
816 
817       Flags = TBDFlags::None;
818       if (!File->isApplicationExtensionSafe())
819         Flags |= TBDFlags::NotApplicationExtensionSafe;
820 
821       if (!File->isTwoLevelNamespace())
822         Flags |= TBDFlags::FlatNamespace;
823 
824       if (File->isInstallAPI())
825         Flags |= TBDFlags::InstallAPI;
826 
827       {
828         std::map<std::string, TargetList> valueToTargetList;
829         for (const auto &it : File->umbrellas())
830           valueToTargetList[it.second].emplace_back(it.first);
831 
832         for (const auto &it : valueToTargetList) {
833           UmbrellaSection CurrentSection;
834           CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
835                                         it.second.begin(), it.second.end());
836           CurrentSection.Umbrella = it.first;
837           ParentUmbrellas.emplace_back(std::move(CurrentSection));
838         }
839       }
840 
841       assignTargetsToLibrary(File->allowableClients(), AllowableClients);
842       assignTargetsToLibrary(File->reexportedLibraries(), ReexportedLibraries);
843 
844       auto handleSymbols =
845           [](SectionList &CurrentSections,
846              InterfaceFile::const_filtered_symbol_range Symbols,
847              std::function<bool(const Symbol *)> Pred) {
848             std::set<TargetList> TargetSet;
849             std::map<const Symbol *, TargetList> SymbolToTargetList;
850             for (const auto *Symbol : Symbols) {
851               if (!Pred(Symbol))
852                 continue;
853               TargetList Targets(Symbol->targets());
854               SymbolToTargetList[Symbol] = Targets;
855               TargetSet.emplace(std::move(Targets));
856             }
857             for (const auto &TargetIDs : TargetSet) {
858               SymbolSection CurrentSection;
859               CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
860                                             TargetIDs.begin(), TargetIDs.end());
861 
862               for (const auto &IT : SymbolToTargetList) {
863                 if (IT.second != TargetIDs)
864                   continue;
865 
866                 const auto *Symbol = IT.first;
867                 switch (Symbol->getKind()) {
868                 case SymbolKind::GlobalSymbol:
869                   if (Symbol->isWeakDefined())
870                     CurrentSection.WeakSymbols.emplace_back(Symbol->getName());
871                   else if (Symbol->isThreadLocalValue())
872                     CurrentSection.TlvSymbols.emplace_back(Symbol->getName());
873                   else
874                     CurrentSection.Symbols.emplace_back(Symbol->getName());
875                   break;
876                 case SymbolKind::ObjectiveCClass:
877                   CurrentSection.Classes.emplace_back(Symbol->getName());
878                   break;
879                 case SymbolKind::ObjectiveCClassEHType:
880                   CurrentSection.ClassEHs.emplace_back(Symbol->getName());
881                   break;
882                 case SymbolKind::ObjectiveCInstanceVariable:
883                   CurrentSection.Ivars.emplace_back(Symbol->getName());
884                   break;
885                 }
886               }
887               sort(CurrentSection.Symbols);
888               sort(CurrentSection.Classes);
889               sort(CurrentSection.ClassEHs);
890               sort(CurrentSection.Ivars);
891               sort(CurrentSection.WeakSymbols);
892               sort(CurrentSection.TlvSymbols);
893               CurrentSections.emplace_back(std::move(CurrentSection));
894             }
895           };
896 
897       handleSymbols(Exports, File->exports(), [](const Symbol *Symbol) {
898         return !Symbol->isReexported();
899       });
900       handleSymbols(Reexports, File->exports(), [](const Symbol *Symbol) {
901         return Symbol->isReexported();
902       });
903       handleSymbols(Undefineds, File->undefineds(),
904                     [](const Symbol *Symbol) { return true; });
905     }
906 
denormalizellvm::yaml::MappingTraits::NormalizedTBD_V4907     const InterfaceFile *denormalize(IO &IO) {
908       auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
909       assert(Ctx);
910 
911       auto *File = new InterfaceFile;
912       File->setPath(Ctx->Path);
913       File->setFileType(Ctx->FileKind);
914       for (auto &id : UUIDs)
915         File->addUUID(id.TargetID, id.Value);
916       File->addTargets(Targets);
917       File->setInstallName(InstallName);
918       File->setCurrentVersion(CurrentVersion);
919       File->setCompatibilityVersion(CompatibilityVersion);
920       File->setSwiftABIVersion(SwiftABIVersion);
921       for (const auto &CurrentSection : ParentUmbrellas)
922         for (const auto &target : CurrentSection.Targets)
923           File->addParentUmbrella(target, CurrentSection.Umbrella);
924       File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
925       File->setApplicationExtensionSafe(
926           !(Flags & TBDFlags::NotApplicationExtensionSafe));
927       File->setInstallAPI(Flags & TBDFlags::InstallAPI);
928 
929       for (const auto &CurrentSection : AllowableClients) {
930         for (const auto &lib : CurrentSection.Values)
931           for (const auto &Target : CurrentSection.Targets)
932             File->addAllowableClient(lib, Target);
933       }
934 
935       for (const auto &CurrentSection : ReexportedLibraries) {
936         for (const auto &Lib : CurrentSection.Values)
937           for (const auto &Target : CurrentSection.Targets)
938             File->addReexportedLibrary(Lib, Target);
939       }
940 
941       auto handleSymbols = [File](const SectionList &CurrentSections,
942                                   SymbolFlags Flag = SymbolFlags::None) {
943         for (const auto &CurrentSection : CurrentSections) {
944           for (auto &sym : CurrentSection.Symbols)
945             File->addSymbol(SymbolKind::GlobalSymbol, sym,
946                             CurrentSection.Targets, Flag);
947 
948           for (auto &sym : CurrentSection.Classes)
949             File->addSymbol(SymbolKind::ObjectiveCClass, sym,
950                             CurrentSection.Targets);
951 
952           for (auto &sym : CurrentSection.ClassEHs)
953             File->addSymbol(SymbolKind::ObjectiveCClassEHType, sym,
954                             CurrentSection.Targets);
955 
956           for (auto &sym : CurrentSection.Ivars)
957             File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, sym,
958                             CurrentSection.Targets);
959 
960           for (auto &sym : CurrentSection.WeakSymbols)
961             File->addSymbol(SymbolKind::GlobalSymbol, sym,
962                             CurrentSection.Targets);
963           for (auto &sym : CurrentSection.TlvSymbols)
964             File->addSymbol(SymbolKind::GlobalSymbol, sym,
965                             CurrentSection.Targets,
966                             SymbolFlags::ThreadLocalValue);
967         }
968       };
969 
970       handleSymbols(Exports);
971       handleSymbols(Reexports, SymbolFlags::Rexported);
972       handleSymbols(Undefineds, SymbolFlags::Undefined);
973 
974       return File;
975     }
976 
977     unsigned TBDVersion;
978     std::vector<UUIDv4> UUIDs;
979     TargetList Targets;
980     StringRef InstallName;
981     PackedVersion CurrentVersion;
982     PackedVersion CompatibilityVersion;
983     SwiftVersion SwiftABIVersion{0};
984     std::vector<MetadataSection> AllowableClients;
985     std::vector<MetadataSection> ReexportedLibraries;
986     TBDFlags Flags{TBDFlags::None};
987     std::vector<UmbrellaSection> ParentUmbrellas;
988     SectionList Exports;
989     SectionList Reexports;
990     SectionList Undefineds;
991 
992   private:
assignTargetsToLibraryllvm::yaml::MappingTraits::NormalizedTBD_V4993     void assignTargetsToLibrary(const std::vector<InterfaceFileRef> &Libraries,
994                                 std::vector<MetadataSection> &Section) {
995       std::set<TargetList> targetSet;
996       std::map<const InterfaceFileRef *, TargetList> valueToTargetList;
997       for (const auto &library : Libraries) {
998         TargetList targets(library.targets());
999         valueToTargetList[&library] = targets;
1000         targetSet.emplace(std::move(targets));
1001       }
1002 
1003       for (const auto &targets : targetSet) {
1004         MetadataSection CurrentSection;
1005         CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
1006                                       targets.begin(), targets.end());
1007 
1008         for (const auto &it : valueToTargetList) {
1009           if (it.second != targets)
1010             continue;
1011 
1012           CurrentSection.Values.emplace_back(it.first->getInstallName());
1013         }
1014         llvm::sort(CurrentSection.Values);
1015         Section.emplace_back(std::move(CurrentSection));
1016       }
1017     }
1018   };
1019 
mapKeysToValuesllvm::yaml::MappingTraits1020   static void mapKeysToValues(FileType FileKind, IO &IO,
1021                               const InterfaceFile *&File) {
1022     MappingNormalization<NormalizedTBD, const InterfaceFile *> Keys(IO, File);
1023     IO.mapRequired("archs", Keys->Architectures);
1024     if (FileKind != FileType::TBD_V1)
1025       IO.mapOptional("uuids", Keys->UUIDs);
1026     IO.mapRequired("platform", Keys->Platforms);
1027     if (FileKind != FileType::TBD_V1)
1028       IO.mapOptional("flags", Keys->Flags, TBDFlags::None);
1029     IO.mapRequired("install-name", Keys->InstallName);
1030     IO.mapOptional("current-version", Keys->CurrentVersion,
1031                    PackedVersion(1, 0, 0));
1032     IO.mapOptional("compatibility-version", Keys->CompatibilityVersion,
1033                    PackedVersion(1, 0, 0));
1034     if (FileKind != FileType::TBD_V3)
1035       IO.mapOptional("swift-version", Keys->SwiftABIVersion, SwiftVersion(0));
1036     else
1037       IO.mapOptional("swift-abi-version", Keys->SwiftABIVersion,
1038                      SwiftVersion(0));
1039     IO.mapOptional("objc-constraint", Keys->ObjCConstraint,
1040                    (FileKind == FileType::TBD_V1)
1041                        ? ObjCConstraintType::None
1042                        : ObjCConstraintType::Retain_Release);
1043     if (FileKind != FileType::TBD_V1)
1044       IO.mapOptional("parent-umbrella", Keys->ParentUmbrella, StringRef());
1045     IO.mapOptional("exports", Keys->Exports);
1046     if (FileKind != FileType::TBD_V1)
1047       IO.mapOptional("undefineds", Keys->Undefineds);
1048   }
1049 
mapKeysToValuesV4llvm::yaml::MappingTraits1050   static void mapKeysToValuesV4(IO &IO, const InterfaceFile *&File) {
1051     MappingNormalization<NormalizedTBD_V4, const InterfaceFile *> Keys(IO,
1052                                                                        File);
1053     IO.mapTag("!tapi-tbd", true);
1054     IO.mapRequired("tbd-version", Keys->TBDVersion);
1055     IO.mapRequired("targets", Keys->Targets);
1056     IO.mapOptional("uuids", Keys->UUIDs);
1057     IO.mapOptional("flags", Keys->Flags, TBDFlags::None);
1058     IO.mapRequired("install-name", Keys->InstallName);
1059     IO.mapOptional("current-version", Keys->CurrentVersion,
1060                    PackedVersion(1, 0, 0));
1061     IO.mapOptional("compatibility-version", Keys->CompatibilityVersion,
1062                    PackedVersion(1, 0, 0));
1063     IO.mapOptional("swift-abi-version", Keys->SwiftABIVersion, SwiftVersion(0));
1064     IO.mapOptional("parent-umbrella", Keys->ParentUmbrellas);
1065     auto OptionKind = MetadataSection::Option::Clients;
1066     IO.mapOptionalWithContext("allowable-clients", Keys->AllowableClients,
1067                               OptionKind);
1068     OptionKind = MetadataSection::Option::Libraries;
1069     IO.mapOptionalWithContext("reexported-libraries", Keys->ReexportedLibraries,
1070                               OptionKind);
1071     IO.mapOptional("exports", Keys->Exports);
1072     IO.mapOptional("reexports", Keys->Reexports);
1073     IO.mapOptional("undefineds", Keys->Undefineds);
1074   }
1075 };
1076 
1077 template <>
1078 struct DocumentListTraits<std::vector<const MachO::InterfaceFile *>> {
sizellvm::yaml::DocumentListTraits1079   static size_t size(IO &IO, std::vector<const MachO::InterfaceFile *> &Seq) {
1080     return Seq.size();
1081   }
1082   static const InterfaceFile *&
elementllvm::yaml::DocumentListTraits1083   element(IO &IO, std::vector<const InterfaceFile *> &Seq, size_t Index) {
1084     if (Index >= Seq.size())
1085       Seq.resize(Index + 1);
1086     return Seq[Index];
1087   }
1088 };
1089 
1090 } // end namespace yaml.
1091 
1092 namespace MachO {
DiagHandler(const SMDiagnostic & Diag,void * Context)1093 static void DiagHandler(const SMDiagnostic &Diag, void *Context) {
1094   auto *File = static_cast<TextAPIContext *>(Context);
1095   SmallString<1024> Message;
1096   raw_svector_ostream S(Message);
1097 
1098   SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), File->Path,
1099                        Diag.getLineNo(), Diag.getColumnNo(), Diag.getKind(),
1100                        Diag.getMessage(), Diag.getLineContents(),
1101                        Diag.getRanges(), Diag.getFixIts());
1102 
1103   NewDiag.print(nullptr, S);
1104   File->ErrorMessage = ("malformed file\n" + Message).str();
1105 }
1106 
1107 Expected<std::unique_ptr<InterfaceFile>>
get(MemoryBufferRef InputBuffer)1108 TextAPIReader::get(MemoryBufferRef InputBuffer) {
1109   TextAPIContext Ctx;
1110   Ctx.Path = InputBuffer.getBufferIdentifier();
1111   yaml::Input YAMLIn(InputBuffer.getBuffer(), &Ctx, DiagHandler, &Ctx);
1112 
1113   // Fill vector with interface file objects created by parsing the YAML file.
1114   std::vector<const InterfaceFile *> Files;
1115   YAMLIn >> Files;
1116 
1117   // YAMLIn dynamically allocates for Interface file and in case of error,
1118   // memory leak will occur unless wrapped around unique_ptr
1119   auto File = std::unique_ptr<InterfaceFile>(
1120       const_cast<InterfaceFile *>(Files.front()));
1121 
1122   if (YAMLIn.error())
1123     return make_error<StringError>(Ctx.ErrorMessage, YAMLIn.error());
1124 
1125   return std::move(File);
1126 }
1127 
writeToStream(raw_ostream & OS,const InterfaceFile & File)1128 Error TextAPIWriter::writeToStream(raw_ostream &OS, const InterfaceFile &File) {
1129   TextAPIContext Ctx;
1130   Ctx.Path = File.getPath();
1131   Ctx.FileKind = File.getFileType();
1132   llvm::yaml::Output YAMLOut(OS, &Ctx, /*WrapColumn=*/80);
1133 
1134   std::vector<const InterfaceFile *> Files;
1135   Files.emplace_back(&File);
1136 
1137   // Stream out yaml.
1138   YAMLOut << Files;
1139 
1140   return Error::success();
1141 }
1142 
1143 } // end namespace MachO.
1144 } // end namespace llvm.
1145