1 //===- TextStub.cpp -------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
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
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
61 weak-def-symbols: [] # Optional: List of weak defined symbols
62 thread-local-symbols: [] # Optional: List of thread local symbols
67 YAML Format specification.
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)
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
83 undefineds: # List of undefineds sections
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
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.
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
136 objc-ivars: [] # Optional: List of Objective C Instance
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
147 objc-ivars: [] # Optional: List of Objective C Instance Variables
148 weak-ref-symbols: [] # Optional: List of weak defined symbols
152 using namespace llvm
;
153 using namespace llvm::yaml
;
154 using namespace llvm::MachO
;
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
;
179 enum TBDFlags
: unsigned {
181 FlatNamespace
= 1U << 0,
182 NotApplicationExtensionSafe
= 1U << 1,
183 InstallAPI
= 1U << 2,
184 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/InstallAPI
),
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
)
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
);
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
)
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());
306 Section
.Symbols
.emplace_back(Symbol
->getName());
308 case SymbolKind::ObjectiveCClass
:
309 if (File
->getFileType() != FileType::TBD_V3
)
310 Section
.Classes
.emplace_back(
311 copyString("_" + Symbol
->getName().str()));
313 Section
.Classes
.emplace_back(Symbol
->getName());
315 case SymbolKind::ObjectiveCClassEHType
:
316 if (File
->getFileType() != FileType::TBD_V3
)
317 Section
.Symbols
.emplace_back(
318 copyString("_OBJC_EHTYPE_$_" + Symbol
->getName().str()));
320 Section
.ClassEHs
.emplace_back(Symbol
->getName());
322 case SymbolKind::ObjectiveCInstanceVariable
:
323 if (File
->getFileType() != FileType::TBD_V3
)
324 Section
.IVars
.emplace_back(
325 copyString("_" + Symbol
->getName().str()));
327 Section
.IVars
.emplace_back(Symbol
->getName());
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
));
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
)
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());
364 Section
.Symbols
.emplace_back(Symbol
->getName());
366 case SymbolKind::ObjectiveCClass
:
367 if (File
->getFileType() != FileType::TBD_V3
)
368 Section
.Classes
.emplace_back(
369 copyString("_" + Symbol
->getName().str()));
371 Section
.Classes
.emplace_back(Symbol
->getName());
373 case SymbolKind::ObjectiveCClassEHType
:
374 if (File
->getFileType() != FileType::TBD_V3
)
375 Section
.Symbols
.emplace_back(
376 copyString("_OBJC_EHTYPE_$_" + Symbol
->getName().str()));
378 Section
.ClassEHs
.emplace_back(Symbol
->getName());
380 case SymbolKind::ObjectiveCInstanceVariable
:
381 if (File
->getFileType() != FileType::TBD_V3
)
382 Section
.IVars
.emplace_back(
383 copyString("_" + Symbol
->getName().str()));
385 Section
.IVars
.emplace_back(Symbol
->getName());
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());
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();
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
);
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
);
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
);
504 llvm::BumpPtrAllocator Allocator
;
505 StringRef
copyString(StringRef String
) {
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-v3", false))
538 Ctx
->FileKind
= FileType::TBD_V3
;
539 else if (IO
.mapTag("!tapi-tbd-v2", 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
;
545 IO
.setError("unsupported file type");
550 // Set file type when writing.
551 if (IO
.outputting()) {
552 switch (Ctx
->FileKind
) {
554 llvm_unreachable("unexpected file type");
555 case FileType::TBD_V1
:
556 // Don't write the tag into the .tbd file for TBD v1.
558 case FileType::TBD_V2
:
559 IO
.mapTag("!tapi-tbd-v2", true);
561 case FileType::TBD_V3
:
562 IO
.mapTag("!tapi-tbd-v3", true);
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));
581 IO
.mapOptional("swift-abi-version", Keys
->SwiftABIVersion
,
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
);
596 struct DocumentListTraits
<std::vector
<const MachO::InterfaceFile
*>> {
597 static size_t size(IO
&IO
, std::vector
<const MachO::InterfaceFile
*> &Seq
) {
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);
608 } // end namespace yaml.
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(MemoryBufferRef InputBuffer
) {
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
;
635 // YAMLIn dynamically allocates for Interface file and in case of error,
636 // memory leak will occur unless wrapped around unique_ptr
637 auto File
= std::unique_ptr
<InterfaceFile
>(
638 const_cast<InterfaceFile
*>(Files
.front()));
641 return make_error
<StringError
>(Ctx
.ErrorMessage
, YAMLIn
.error());
643 return std::move(File
);
646 Error
TextAPIWriter::writeToStream(raw_ostream
&OS
, const InterfaceFile
&File
) {
648 Ctx
.Path
= File
.getPath();
649 Ctx
.FileKind
= File
.getFileType();
650 llvm::yaml::Output
YAMLOut(OS
, &Ctx
, /*WrapColumn=*/80);
652 std::vector
<const InterfaceFile
*> Files
;
653 Files
.emplace_back(&File
);
658 return Error::success();
661 } // end namespace MachO.
662 } // end namespace llvm.