[MIPS GlobalISel] Select MSA vector generic and builtin add
[llvm-complete.git] / lib / TextAPI / MachO / TextStub.cpp
blob0584e43d5893fefe929fcd557f6de98c6749ce5a
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
153 YAML Format specification.
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
174 re-exports: # List of reexport sections
176 undefineds: # List of undefineds sections
179 Each export and reexport section is defined as following:
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
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
202 // clang-format on
204 using namespace llvm;
205 using namespace llvm::yaml;
206 using namespace llvm::MachO;
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;
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;
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;
241 struct MetadataSection {
242 enum Option { Clients, Libraries };
243 std::vector<Target> Targets;
244 std::vector<FlowStringRef> Values;
247 struct UmbrellaSection {
248 std::vector<Target> Targets;
249 std::string Umbrella;
252 // UUID's for TBDv4 are mapped to target not arch
253 struct UUIDv4 {
254 Target TargetID;
255 std::string Value;
257 UUIDv4() = default;
258 UUIDv4(const Target &TargetID, const std::string &Value)
259 : TargetID(TargetID), Value(Value) {}
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),
270 // clang-format on
271 } // end anonymous namespace.
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)
283 namespace llvm {
284 namespace yaml {
286 template <> struct MappingTraits<ExportSection> {
287 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");
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);
308 template <> struct MappingTraits<UndefinedSection> {
309 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");
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);
324 template <> struct MappingTraits<SymbolSection> {
325 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);
336 template <> struct MappingTraits<UmbrellaSection> {
337 static void mapping(IO &IO, UmbrellaSection &Section) {
338 IO.mapRequired("targets", Section.Targets);
339 IO.mapRequired("umbrella", Section.Umbrella);
343 template <> struct MappingTraits<UUIDv4> {
344 static void mapping(IO &IO, UUIDv4 &UUID) {
345 IO.mapRequired("target", UUID.TargetID);
346 IO.mapRequired("value", UUID.Value);
350 template <>
351 struct MappingContextTraits<MetadataSection, MetadataSection::Option> {
352 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;
363 llvm_unreachable("unexpected option for metadata");
367 template <> struct ScalarBitSetTraits<TBDFlags> {
368 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);
376 template <> struct ScalarTraits<Target> {
377 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;
413 static StringRef input(StringRef Scalar, void *, Target &Value) {
414 auto Result = Target::create(Scalar);
415 if (!Result)
416 return toString(Result.takeError());
418 Value = *Result;
419 if (Value.Arch == AK_unknown)
420 return "unknown architecture";
421 if (Value.Platform == PlatformKind::unknown)
422 return "unknown platform";
424 return {};
427 static QuotingType mustQuote(StringRef) { return QuotingType::None; }
430 template <> struct MappingTraits<const InterfaceFile *> {
431 struct NormalizedTBD {
432 explicit NormalizedTBD(IO &IO) {}
433 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();
443 Flags = TBDFlags::None;
444 if (!File->isApplicationExtensionSafe())
445 Flags |= TBDFlags::NotApplicationExtensionSafe;
447 if (!File->isTwoLevelNamespace())
448 Flags |= TBDFlags::FlatNamespace;
450 if (File->isInstallAPI())
451 Flags |= TBDFlags::InstallAPI;
453 for (const auto &Iter : File->umbrellas()) {
454 ParentUmbrella = Iter.second;
455 break;
458 std::set<ArchitectureSet> ArchSet;
459 for (const auto &Library : File->allowableClients())
460 ArchSet.insert(Library.getArchitectures());
462 for (const auto &Library : File->reexportedLibraries())
463 ArchSet.insert(Library.getArchitectures());
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);
472 for (auto Architectures : ArchSet) {
473 ExportSection Section;
474 Section.Architectures = Architectures;
476 for (const auto &Library : File->allowableClients())
477 if (Library.getArchitectures() == Architectures)
478 Section.AllowableClients.emplace_back(Library.getInstallName());
480 for (const auto &Library : File->reexportedLibraries())
481 if (Library.getArchitectures() == Architectures)
482 Section.ReexportedLibraries.emplace_back(Library.getInstallName());
484 for (const auto &SymArch : SymbolToArchSet) {
485 if (SymArch.second != Architectures)
486 continue;
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;
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));
531 ArchSet.clear();
532 SymbolToArchSet.clear();
534 for (const auto *Symbol : File->undefineds()) {
535 auto Architectures = Symbol->getArchitectures();
536 SymbolToArchSet[Symbol] = Architectures;
537 ArchSet.insert(Architectures);
540 for (auto Architectures : ArchSet) {
541 UndefinedSection Section;
542 Section.Architectures = Architectures;
544 for (const auto &SymArch : SymbolToArchSet) {
545 if (SymArch.second != Architectures)
546 continue;
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;
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));
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.
594 TargetList synthesizeTargets(ArchitectureSet Architectures,
595 const PlatformSet &Platforms) {
596 TargetList Targets;
598 for (auto Platform : Platforms) {
599 Platform = mapToPlatformKind(Platform, Architectures.hasX86());
601 for (const auto &&Architecture : Architectures) {
602 if ((Architecture == AK_i386) &&
603 (Platform == PlatformKind::macCatalyst))
604 continue;
606 Targets.emplace_back(Architecture, Platform);
609 return Targets;
612 const InterfaceFile *denormalize(IO &IO) {
613 auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
614 assert(Ctx);
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);
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);
640 for (const auto &Section : Exports) {
641 const auto Targets =
642 synthesizeTargets(Section.Architectures, Platforms);
644 for (const auto &Lib : Section.AllowableClients)
645 for (const auto &Target : Targets)
646 File->addAllowableClient(Lib, Target);
648 for (const auto &Lib : Section.ReexportedLibraries)
649 for (const auto &Target : Targets)
650 File->addReexportedLibrary(Lib, Target);
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);
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);
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);
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);
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);
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);
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);
713 for (auto &Symbol : Section.WeakRefSymbols)
714 File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
715 SymbolFlags::Undefined | SymbolFlags::WeakReferenced);
718 return File;
721 llvm::BumpPtrAllocator Allocator;
722 StringRef copyString(StringRef String) {
723 if (String.empty())
724 return {};
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());
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;
745 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;
761 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");
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;
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;
798 mapKeysToValues(Ctx->FileKind, IO, File);
801 using SectionList = std::vector<SymbolSection>;
802 struct NormalizedTBD_V4 {
803 explicit NormalizedTBD_V4(IO &IO) {}
804 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();
817 Flags = TBDFlags::None;
818 if (!File->isApplicationExtensionSafe())
819 Flags |= TBDFlags::NotApplicationExtensionSafe;
821 if (!File->isTwoLevelNamespace())
822 Flags |= TBDFlags::FlatNamespace;
824 if (File->isInstallAPI())
825 Flags |= TBDFlags::InstallAPI;
828 std::map<std::string, TargetList> valueToTargetList;
829 for (const auto &it : File->umbrellas())
830 valueToTargetList[it.second].emplace_back(it.first);
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));
841 assignTargetsToLibrary(File->allowableClients(), AllowableClients);
842 assignTargetsToLibrary(File->reexportedLibraries(), ReexportedLibraries);
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));
857 for (const auto &TargetIDs : TargetSet) {
858 SymbolSection CurrentSection;
859 CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
860 TargetIDs.begin(), TargetIDs.end());
862 for (const auto &IT : SymbolToTargetList) {
863 if (IT.second != TargetIDs)
864 continue;
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;
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));
897 handleSymbols(Exports, File->exports(), [](const Symbol *Symbol) {
898 return !Symbol->isReexported();
900 handleSymbols(Reexports, File->exports(), [](const Symbol *Symbol) {
901 return Symbol->isReexported();
903 handleSymbols(Undefineds, File->undefineds(),
904 [](const Symbol *Symbol) { return true; });
907 const InterfaceFile *denormalize(IO &IO) {
908 auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
909 assert(Ctx);
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);
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);
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);
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);
948 for (auto &sym : CurrentSection.Classes)
949 File->addSymbol(SymbolKind::ObjectiveCClass, sym,
950 CurrentSection.Targets);
952 for (auto &sym : CurrentSection.ClassEHs)
953 File->addSymbol(SymbolKind::ObjectiveCClassEHType, sym,
954 CurrentSection.Targets);
956 for (auto &sym : CurrentSection.Ivars)
957 File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, sym,
958 CurrentSection.Targets);
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);
970 handleSymbols(Exports);
971 handleSymbols(Reexports, SymbolFlags::Rexported);
972 handleSymbols(Undefineds, SymbolFlags::Undefined);
974 return File;
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;
992 private:
993 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));
1003 for (const auto &targets : targetSet) {
1004 MetadataSection CurrentSection;
1005 CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
1006 targets.begin(), targets.end());
1008 for (const auto &it : valueToTargetList) {
1009 if (it.second != targets)
1010 continue;
1012 CurrentSection.Values.emplace_back(it.first->getInstallName());
1014 llvm::sort(CurrentSection.Values);
1015 Section.emplace_back(std::move(CurrentSection));
1020 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);
1050 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);
1077 template <>
1078 struct DocumentListTraits<std::vector<const MachO::InterfaceFile *>> {
1079 static size_t size(IO &IO, std::vector<const MachO::InterfaceFile *> &Seq) {
1080 return Seq.size();
1082 static const InterfaceFile *&
1083 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];
1090 } // end namespace yaml.
1092 namespace MachO {
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);
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());
1103 NewDiag.print(nullptr, S);
1104 File->ErrorMessage = ("malformed file\n" + Message).str();
1107 Expected<std::unique_ptr<InterfaceFile>>
1108 TextAPIReader::get(MemoryBufferRef InputBuffer) {
1109 TextAPIContext Ctx;
1110 Ctx.Path = InputBuffer.getBufferIdentifier();
1111 yaml::Input YAMLIn(InputBuffer.getBuffer(), &Ctx, DiagHandler, &Ctx);
1113 // Fill vector with interface file objects created by parsing the YAML file.
1114 std::vector<const InterfaceFile *> Files;
1115 YAMLIn >> Files;
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()));
1122 if (YAMLIn.error())
1123 return make_error<StringError>(Ctx.ErrorMessage, YAMLIn.error());
1125 return std::move(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);
1134 std::vector<const InterfaceFile *> Files;
1135 Files.emplace_back(&File);
1137 // Stream out yaml.
1138 YAMLOut << Files;
1140 return Error::success();
1143 } // end namespace MachO.
1144 } // end namespace llvm.