Recommit "[GVN] Preserve loop related analysis/canonical forms."
[llvm-core.git] / lib / TextAPI / MachO / TextStub.cpp
blob799ebdc883abc8f22ab897e5c66570a1b02efea2
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.
11 //===----------------------------------------------------------------------===//
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>
31 // clang-format off
34 YAML Format specification.
36 The TBD v1 format only support two level address libraries and is per
37 definition application extension safe.
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 ...
52 Each export section is defined as following:
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
67 YAML Format specification.
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 ...
86 Each export section is defined as following:
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
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
108 YAML Format specification.
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
124 undefineds: # List of undefineds sections
127 Each export section is defined as following:
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
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
150 // clang-format on
152 using namespace llvm;
153 using namespace llvm::yaml;
154 using namespace llvm::MachO;
156 namespace {
157 struct ExportSection {
158 std::vector<Architecture> Architectures;
159 std::vector<FlowStringRef> AllowableClients;
160 std::vector<FlowStringRef> ReexportedLibraries;
161 std::vector<FlowStringRef> Symbols;
162 std::vector<FlowStringRef> Classes;
163 std::vector<FlowStringRef> ClassEHs;
164 std::vector<FlowStringRef> IVars;
165 std::vector<FlowStringRef> WeakDefSymbols;
166 std::vector<FlowStringRef> TLVSymbols;
169 struct UndefinedSection {
170 std::vector<Architecture> Architectures;
171 std::vector<FlowStringRef> Symbols;
172 std::vector<FlowStringRef> Classes;
173 std::vector<FlowStringRef> ClassEHs;
174 std::vector<FlowStringRef> IVars;
175 std::vector<FlowStringRef> WeakRefSymbols;
178 // clang-format off
179 enum TBDFlags : unsigned {
180 None = 0U,
181 FlatNamespace = 1U << 0,
182 NotApplicationExtensionSafe = 1U << 1,
183 InstallAPI = 1U << 2,
184 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/InstallAPI),
186 // clang-format on
187 } // end anonymous namespace.
189 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(Architecture)
190 LLVM_YAML_IS_SEQUENCE_VECTOR(ExportSection)
191 LLVM_YAML_IS_SEQUENCE_VECTOR(UndefinedSection)
193 namespace llvm {
194 namespace yaml {
196 template <> struct MappingTraits<ExportSection> {
197 static void mapping(IO &IO, ExportSection &Section) {
198 const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
199 assert((!Ctx || (Ctx && Ctx->FileKind != FileType::Invalid)) &&
200 "File type is not set in YAML context");
202 IO.mapRequired("archs", Section.Architectures);
203 if (Ctx->FileKind == FileType::TBD_V1)
204 IO.mapOptional("allowed-clients", Section.AllowableClients);
205 else
206 IO.mapOptional("allowable-clients", Section.AllowableClients);
207 IO.mapOptional("re-exports", Section.ReexportedLibraries);
208 IO.mapOptional("symbols", Section.Symbols);
209 IO.mapOptional("objc-classes", Section.Classes);
210 if (Ctx->FileKind == FileType::TBD_V3)
211 IO.mapOptional("objc-eh-types", Section.ClassEHs);
212 IO.mapOptional("objc-ivars", Section.IVars);
213 IO.mapOptional("weak-def-symbols", Section.WeakDefSymbols);
214 IO.mapOptional("thread-local-symbols", Section.TLVSymbols);
218 template <> struct MappingTraits<UndefinedSection> {
219 static void mapping(IO &IO, UndefinedSection &Section) {
220 const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
221 assert((!Ctx || (Ctx && Ctx->FileKind != FileType::Invalid)) &&
222 "File type is not set in YAML context");
224 IO.mapRequired("archs", Section.Architectures);
225 IO.mapOptional("symbols", Section.Symbols);
226 IO.mapOptional("objc-classes", Section.Classes);
227 if (Ctx->FileKind == FileType::TBD_V3)
228 IO.mapOptional("objc-eh-types", Section.ClassEHs);
229 IO.mapOptional("objc-ivars", Section.IVars);
230 IO.mapOptional("weak-ref-symbols", Section.WeakRefSymbols);
234 template <> struct ScalarBitSetTraits<TBDFlags> {
235 static void bitset(IO &IO, TBDFlags &Flags) {
236 IO.bitSetCase(Flags, "flat_namespace", TBDFlags::FlatNamespace);
237 IO.bitSetCase(Flags, "not_app_extension_safe",
238 TBDFlags::NotApplicationExtensionSafe);
239 IO.bitSetCase(Flags, "installapi", TBDFlags::InstallAPI);
243 template <> struct MappingTraits<const InterfaceFile *> {
244 struct NormalizedTBD {
245 explicit NormalizedTBD(IO &IO) {}
246 NormalizedTBD(IO &IO, const InterfaceFile *&File) {
247 Architectures = File->getArchitectures();
248 UUIDs = File->uuids();
249 Platform = File->getPlatform();
250 InstallName = File->getInstallName();
251 CurrentVersion = PackedVersion(File->getCurrentVersion());
252 CompatibilityVersion = PackedVersion(File->getCompatibilityVersion());
253 SwiftABIVersion = File->getSwiftABIVersion();
254 ObjCConstraint = File->getObjCConstraint();
256 Flags = TBDFlags::None;
257 if (!File->isApplicationExtensionSafe())
258 Flags |= TBDFlags::NotApplicationExtensionSafe;
260 if (!File->isTwoLevelNamespace())
261 Flags |= TBDFlags::FlatNamespace;
263 if (File->isInstallAPI())
264 Flags |= TBDFlags::InstallAPI;
266 ParentUmbrella = File->getParentUmbrella();
268 std::set<ArchitectureSet> ArchSet;
269 for (const auto &Library : File->allowableClients())
270 ArchSet.insert(Library.getArchitectures());
272 for (const auto &Library : File->reexportedLibraries())
273 ArchSet.insert(Library.getArchitectures());
275 std::map<const Symbol *, ArchitectureSet> SymbolToArchSet;
276 for (const auto *Symbol : File->exports()) {
277 auto Architectures = Symbol->getArchitectures();
278 SymbolToArchSet[Symbol] = Architectures;
279 ArchSet.insert(Architectures);
282 for (auto Architectures : ArchSet) {
283 ExportSection Section;
284 Section.Architectures = Architectures;
286 for (const auto &Library : File->allowableClients())
287 if (Library.getArchitectures() == Architectures)
288 Section.AllowableClients.emplace_back(Library.getInstallName());
290 for (const auto &Library : File->reexportedLibraries())
291 if (Library.getArchitectures() == Architectures)
292 Section.ReexportedLibraries.emplace_back(Library.getInstallName());
294 for (const auto &SymArch : SymbolToArchSet) {
295 if (SymArch.second != Architectures)
296 continue;
298 const auto *Symbol = SymArch.first;
299 switch (Symbol->getKind()) {
300 case SymbolKind::GlobalSymbol:
301 if (Symbol->isWeakDefined())
302 Section.WeakDefSymbols.emplace_back(Symbol->getName());
303 else if (Symbol->isThreadLocalValue())
304 Section.TLVSymbols.emplace_back(Symbol->getName());
305 else
306 Section.Symbols.emplace_back(Symbol->getName());
307 break;
308 case SymbolKind::ObjectiveCClass:
309 if (File->getFileType() != FileType::TBD_V3)
310 Section.Classes.emplace_back(
311 copyString("_" + Symbol->getName().str()));
312 else
313 Section.Classes.emplace_back(Symbol->getName());
314 break;
315 case SymbolKind::ObjectiveCClassEHType:
316 if (File->getFileType() != FileType::TBD_V3)
317 Section.Symbols.emplace_back(
318 copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str()));
319 else
320 Section.ClassEHs.emplace_back(Symbol->getName());
321 break;
322 case SymbolKind::ObjectiveCInstanceVariable:
323 if (File->getFileType() != FileType::TBD_V3)
324 Section.IVars.emplace_back(
325 copyString("_" + Symbol->getName().str()));
326 else
327 Section.IVars.emplace_back(Symbol->getName());
328 break;
331 llvm::sort(Section.Symbols.begin(), Section.Symbols.end());
332 llvm::sort(Section.Classes.begin(), Section.Classes.end());
333 llvm::sort(Section.ClassEHs.begin(), Section.ClassEHs.end());
334 llvm::sort(Section.IVars.begin(), Section.IVars.end());
335 llvm::sort(Section.WeakDefSymbols.begin(),
336 Section.WeakDefSymbols.end());
337 llvm::sort(Section.TLVSymbols.begin(), Section.TLVSymbols.end());
338 Exports.emplace_back(std::move(Section));
341 ArchSet.clear();
342 SymbolToArchSet.clear();
344 for (const auto *Symbol : File->undefineds()) {
345 auto Architectures = Symbol->getArchitectures();
346 SymbolToArchSet[Symbol] = Architectures;
347 ArchSet.insert(Architectures);
350 for (auto Architectures : ArchSet) {
351 UndefinedSection Section;
352 Section.Architectures = Architectures;
354 for (const auto &SymArch : SymbolToArchSet) {
355 if (SymArch.second != Architectures)
356 continue;
358 const auto *Symbol = SymArch.first;
359 switch (Symbol->getKind()) {
360 case SymbolKind::GlobalSymbol:
361 if (Symbol->isWeakReferenced())
362 Section.WeakRefSymbols.emplace_back(Symbol->getName());
363 else
364 Section.Symbols.emplace_back(Symbol->getName());
365 break;
366 case SymbolKind::ObjectiveCClass:
367 if (File->getFileType() != FileType::TBD_V3)
368 Section.Classes.emplace_back(
369 copyString("_" + Symbol->getName().str()));
370 else
371 Section.Classes.emplace_back(Symbol->getName());
372 break;
373 case SymbolKind::ObjectiveCClassEHType:
374 if (File->getFileType() != FileType::TBD_V3)
375 Section.Symbols.emplace_back(
376 copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str()));
377 else
378 Section.ClassEHs.emplace_back(Symbol->getName());
379 break;
380 case SymbolKind::ObjectiveCInstanceVariable:
381 if (File->getFileType() != FileType::TBD_V3)
382 Section.IVars.emplace_back(
383 copyString("_" + Symbol->getName().str()));
384 else
385 Section.IVars.emplace_back(Symbol->getName());
386 break;
389 llvm::sort(Section.Symbols.begin(), Section.Symbols.end());
390 llvm::sort(Section.Classes.begin(), Section.Classes.end());
391 llvm::sort(Section.ClassEHs.begin(), Section.ClassEHs.end());
392 llvm::sort(Section.IVars.begin(), Section.IVars.end());
393 llvm::sort(Section.WeakRefSymbols.begin(),
394 Section.WeakRefSymbols.end());
395 Undefineds.emplace_back(std::move(Section));
399 const InterfaceFile *denormalize(IO &IO) {
400 auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
401 assert(Ctx);
403 auto *File = new InterfaceFile;
404 File->setPath(Ctx->Path);
405 File->setFileType(Ctx->FileKind);
406 for (auto &ID : UUIDs)
407 File->addUUID(ID.first, ID.second);
408 File->setPlatform(Platform);
409 File->setArchitectures(Architectures);
410 File->setInstallName(InstallName);
411 File->setCurrentVersion(CurrentVersion);
412 File->setCompatibilityVersion(CompatibilityVersion);
413 File->setSwiftABIVersion(SwiftABIVersion);
414 File->setObjCConstraint(ObjCConstraint);
415 File->setParentUmbrella(ParentUmbrella);
417 if (Ctx->FileKind == FileType::TBD_V1) {
418 File->setTwoLevelNamespace();
419 File->setApplicationExtensionSafe();
420 } else {
421 File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
422 File->setApplicationExtensionSafe(
423 !(Flags & TBDFlags::NotApplicationExtensionSafe));
424 File->setInstallAPI(Flags & TBDFlags::InstallAPI);
427 for (const auto &Section : Exports) {
428 for (const auto &Library : Section.AllowableClients)
429 File->addAllowableClient(Library, Section.Architectures);
430 for (const auto &Library : Section.ReexportedLibraries)
431 File->addReexportedLibrary(Library, Section.Architectures);
433 for (const auto &Symbol : Section.Symbols) {
434 if (Ctx->FileKind != FileType::TBD_V3 &&
435 Symbol.value.startswith("_OBJC_EHTYPE_$_"))
436 File->addSymbol(SymbolKind::ObjectiveCClassEHType,
437 Symbol.value.drop_front(15), Section.Architectures);
438 else
439 File->addSymbol(SymbolKind::GlobalSymbol, Symbol,
440 Section.Architectures);
442 for (auto &Symbol : Section.Classes) {
443 auto Name = Symbol.value;
444 if (Ctx->FileKind != FileType::TBD_V3)
445 Name = Name.drop_front();
446 File->addSymbol(SymbolKind::ObjectiveCClass, Name,
447 Section.Architectures);
449 for (auto &Symbol : Section.ClassEHs)
450 File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol,
451 Section.Architectures);
452 for (auto &Symbol : Section.IVars) {
453 auto Name = Symbol.value;
454 if (Ctx->FileKind != FileType::TBD_V3)
455 Name = Name.drop_front();
456 File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name,
457 Section.Architectures);
459 for (auto &Symbol : Section.WeakDefSymbols)
460 File->addSymbol(SymbolKind::GlobalSymbol, Symbol,
461 Section.Architectures, SymbolFlags::WeakDefined);
462 for (auto &Symbol : Section.TLVSymbols)
463 File->addSymbol(SymbolKind::GlobalSymbol, Symbol,
464 Section.Architectures, SymbolFlags::ThreadLocalValue);
467 for (const auto &Section : Undefineds) {
468 for (auto &Symbol : Section.Symbols) {
469 if (Ctx->FileKind != FileType::TBD_V3 &&
470 Symbol.value.startswith("_OBJC_EHTYPE_$_"))
471 File->addSymbol(SymbolKind::ObjectiveCClassEHType,
472 Symbol.value.drop_front(15), Section.Architectures,
473 SymbolFlags::Undefined);
474 else
475 File->addSymbol(SymbolKind::GlobalSymbol, Symbol,
476 Section.Architectures, SymbolFlags::Undefined);
478 for (auto &Symbol : Section.Classes) {
479 auto Name = Symbol.value;
480 if (Ctx->FileKind != FileType::TBD_V3)
481 Name = Name.drop_front();
482 File->addSymbol(SymbolKind::ObjectiveCClass, Name,
483 Section.Architectures, SymbolFlags::Undefined);
485 for (auto &Symbol : Section.ClassEHs)
486 File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol,
487 Section.Architectures, SymbolFlags::Undefined);
488 for (auto &Symbol : Section.IVars) {
489 auto Name = Symbol.value;
490 if (Ctx->FileKind != FileType::TBD_V3)
491 Name = Name.drop_front();
492 File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name,
493 Section.Architectures, SymbolFlags::Undefined);
495 for (auto &Symbol : Section.WeakRefSymbols)
496 File->addSymbol(SymbolKind::GlobalSymbol, Symbol,
497 Section.Architectures,
498 SymbolFlags::Undefined | SymbolFlags::WeakReferenced);
501 return File;
504 llvm::BumpPtrAllocator Allocator;
505 StringRef copyString(StringRef String) {
506 if (String.empty())
507 return {};
509 void *Ptr = Allocator.Allocate(String.size(), 1);
510 memcpy(Ptr, String.data(), String.size());
511 return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
514 std::vector<Architecture> Architectures;
515 std::vector<UUID> UUIDs;
516 PlatformKind Platform{PlatformKind::unknown};
517 StringRef InstallName;
518 PackedVersion CurrentVersion;
519 PackedVersion CompatibilityVersion;
520 SwiftVersion SwiftABIVersion{0};
521 ObjCConstraintType ObjCConstraint{ObjCConstraintType::None};
522 TBDFlags Flags{TBDFlags::None};
523 StringRef ParentUmbrella;
524 std::vector<ExportSection> Exports;
525 std::vector<UndefinedSection> Undefineds;
528 static void mapping(IO &IO, const InterfaceFile *&File) {
529 auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
530 assert((!Ctx || !IO.outputting() ||
531 (Ctx && Ctx->FileKind != FileType::Invalid)) &&
532 "File type is not set in YAML context");
533 MappingNormalization<NormalizedTBD, const InterfaceFile *> Keys(IO, File);
535 // prope file type when reading.
536 if (!IO.outputting()) {
537 if (IO.mapTag("!tapi-tbd-v2", false))
538 Ctx->FileKind = FileType::TBD_V2;
539 else if (IO.mapTag("!tapi-tbd-v3", false))
540 Ctx->FileKind = FileType::TBD_V2;
541 else if (IO.mapTag("!tapi-tbd-v1", false) ||
542 IO.mapTag("tag:yaml.org,2002:map", false))
543 Ctx->FileKind = FileType::TBD_V1;
544 else {
545 IO.setError("unsupported file type");
546 return;
550 // Set file tyoe when writing.
551 if (IO.outputting()) {
552 switch (Ctx->FileKind) {
553 default:
554 llvm_unreachable("unexpected file type");
555 case FileType::TBD_V1:
556 // Don't write the tag into the .tbd file for TBD v1.
557 break;
558 case FileType::TBD_V2:
559 IO.mapTag("!tapi-tbd-v2", true);
560 break;
561 case FileType::TBD_V3:
562 IO.mapTag("!tapi-tbd-v3", true);
563 break;
567 IO.mapRequired("archs", Keys->Architectures);
568 if (Ctx->FileKind != FileType::TBD_V1)
569 IO.mapOptional("uuids", Keys->UUIDs);
570 IO.mapRequired("platform", Keys->Platform);
571 if (Ctx->FileKind != FileType::TBD_V1)
572 IO.mapOptional("flags", Keys->Flags, TBDFlags::None);
573 IO.mapRequired("install-name", Keys->InstallName);
574 IO.mapOptional("current-version", Keys->CurrentVersion,
575 PackedVersion(1, 0, 0));
576 IO.mapOptional("compatibility-version", Keys->CompatibilityVersion,
577 PackedVersion(1, 0, 0));
578 if (Ctx->FileKind != FileType::TBD_V3)
579 IO.mapOptional("swift-version", Keys->SwiftABIVersion, SwiftVersion(0));
580 else
581 IO.mapOptional("swift-abi-version", Keys->SwiftABIVersion,
582 SwiftVersion(0));
583 IO.mapOptional("objc-constraint", Keys->ObjCConstraint,
584 (Ctx->FileKind == FileType::TBD_V1)
585 ? ObjCConstraintType::None
586 : ObjCConstraintType::Retain_Release);
587 if (Ctx->FileKind != FileType::TBD_V1)
588 IO.mapOptional("parent-umbrella", Keys->ParentUmbrella, StringRef());
589 IO.mapOptional("exports", Keys->Exports);
590 if (Ctx->FileKind != FileType::TBD_V1)
591 IO.mapOptional("undefineds", Keys->Undefineds);
595 template <>
596 struct DocumentListTraits<std::vector<const MachO::InterfaceFile *>> {
597 static size_t size(IO &IO, std::vector<const MachO::InterfaceFile *> &Seq) {
598 return Seq.size();
600 static const InterfaceFile *&
601 element(IO &IO, std::vector<const InterfaceFile *> &Seq, size_t Index) {
602 if (Index >= Seq.size())
603 Seq.resize(Index + 1);
604 return Seq[Index];
608 } // end namespace yaml.
610 namespace MachO {
611 static void DiagHandler(const SMDiagnostic &Diag, void *Context) {
612 auto *File = static_cast<TextAPIContext *>(Context);
613 SmallString<1024> Message;
614 raw_svector_ostream S(Message);
616 SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), File->Path,
617 Diag.getLineNo(), Diag.getColumnNo(), Diag.getKind(),
618 Diag.getMessage(), Diag.getLineContents(),
619 Diag.getRanges(), Diag.getFixIts());
621 NewDiag.print(nullptr, S);
622 File->ErrorMessage = ("malformed file\n" + Message).str();
625 Expected<std::unique_ptr<InterfaceFile>>
626 TextAPIReader::get(std::unique_ptr<MemoryBuffer> InputBuffer) {
627 TextAPIContext Ctx;
628 Ctx.Path = InputBuffer->getBufferIdentifier();
629 yaml::Input YAMLIn(InputBuffer->getBuffer(), &Ctx, DiagHandler, &Ctx);
631 // Fill vector with interface file objects created by parsing the YAML file.
632 std::vector<const InterfaceFile *> Files;
633 YAMLIn >> Files;
635 auto File = std::unique_ptr<InterfaceFile>(
636 const_cast<InterfaceFile *>(Files.front()));
638 if (YAMLIn.error())
639 return make_error<StringError>(Ctx.ErrorMessage, YAMLIn.error());
641 return std::move(File);
644 Error TextAPIWriter::writeToStream(raw_ostream &OS, const InterfaceFile &File) {
645 TextAPIContext Ctx;
646 Ctx.Path = File.getPath();
647 Ctx.FileKind = File.getFileType();
648 llvm::yaml::Output YAMLOut(OS, &Ctx, /*WrapColumn=*/80);
650 std::vector<const InterfaceFile *> Files;
651 Files.emplace_back(&File);
653 // Stream out yaml.
654 YAMLOut << Files;
656 return Error::success();
659 } // end namespace MachO.
660 } // end namespace llvm.