1e6d15924SDimitry Andric //===- TextStub.cpp -------------------------------------------------------===//
2e6d15924SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e6d15924SDimitry Andric //
7e6d15924SDimitry Andric //===----------------------------------------------------------------------===//
8e6d15924SDimitry Andric //
9e6d15924SDimitry Andric // Implements the text stub file reader/writer.
10e6d15924SDimitry Andric //
11e6d15924SDimitry Andric //===----------------------------------------------------------------------===//
12e6d15924SDimitry Andric
13e6d15924SDimitry Andric #include "TextAPIContext.h"
14e6d15924SDimitry Andric #include "TextStubCommon.h"
15e6d15924SDimitry Andric #include "llvm/ADT/BitmaskEnum.h"
16e6d15924SDimitry Andric #include "llvm/ADT/SmallString.h"
17e6d15924SDimitry Andric #include "llvm/ADT/StringRef.h"
18e6d15924SDimitry Andric #include "llvm/Support/Allocator.h"
19e6d15924SDimitry Andric #include "llvm/Support/SourceMgr.h"
20e6d15924SDimitry Andric #include "llvm/Support/YAMLTraits.h"
21e6d15924SDimitry Andric #include "llvm/Support/raw_ostream.h"
22344a3780SDimitry Andric #include "llvm/TextAPI/Architecture.h"
23344a3780SDimitry Andric #include "llvm/TextAPI/ArchitectureSet.h"
24344a3780SDimitry Andric #include "llvm/TextAPI/InterfaceFile.h"
25344a3780SDimitry Andric #include "llvm/TextAPI/PackedVersion.h"
26344a3780SDimitry Andric #include "llvm/TextAPI/TextAPIReader.h"
27344a3780SDimitry Andric #include "llvm/TextAPI/TextAPIWriter.h"
28e6d15924SDimitry Andric #include <algorithm>
29e6d15924SDimitry Andric #include <set>
30e6d15924SDimitry Andric
31e6d15924SDimitry Andric // clang-format off
32e6d15924SDimitry Andric /*
33e6d15924SDimitry Andric
34e6d15924SDimitry Andric YAML Format specification.
35e6d15924SDimitry Andric
36e6d15924SDimitry Andric The TBD v1 format only support two level address libraries and is per
37e6d15924SDimitry Andric definition application extension safe.
38e6d15924SDimitry Andric
39e6d15924SDimitry Andric --- # the tag !tapi-tbd-v1 is optional and
40e6d15924SDimitry Andric # shouldn't be emitted to support older linker.
41e6d15924SDimitry Andric archs: [ armv7, armv7s, arm64 ] # the list of architecture slices that are
42e6d15924SDimitry Andric # supported by this file.
43e6d15924SDimitry Andric platform: ios # Specifies the platform (macosx, ios, etc)
44e6d15924SDimitry Andric install-name: /u/l/libfoo.dylib #
45e6d15924SDimitry Andric current-version: 1.2.3 # Optional: defaults to 1.0
46e6d15924SDimitry Andric compatibility-version: 1.0 # Optional: defaults to 1.0
47e6d15924SDimitry Andric swift-version: 0 # Optional: defaults to 0
48e6d15924SDimitry Andric objc-constraint: none # Optional: defaults to none
49e6d15924SDimitry Andric exports: # List of export sections
50e6d15924SDimitry Andric ...
51e6d15924SDimitry Andric
52e6d15924SDimitry Andric Each export section is defined as following:
53e6d15924SDimitry Andric
54e6d15924SDimitry Andric - archs: [ arm64 ] # the list of architecture slices
55e6d15924SDimitry Andric allowed-clients: [ client ] # Optional: List of clients
56e6d15924SDimitry Andric re-exports: [ ] # Optional: List of re-exports
57e6d15924SDimitry Andric symbols: [ _sym ] # Optional: List of symbols
58e6d15924SDimitry Andric objc-classes: [] # Optional: List of Objective-C classes
59e6d15924SDimitry Andric objc-ivars: [] # Optional: List of Objective C Instance
60e6d15924SDimitry Andric # Variables
61e6d15924SDimitry Andric weak-def-symbols: [] # Optional: List of weak defined symbols
62e6d15924SDimitry Andric thread-local-symbols: [] # Optional: List of thread local symbols
63e6d15924SDimitry Andric */
64e6d15924SDimitry Andric
65e6d15924SDimitry Andric /*
66e6d15924SDimitry Andric
67e6d15924SDimitry Andric YAML Format specification.
68e6d15924SDimitry Andric
69e6d15924SDimitry Andric --- !tapi-tbd-v2
70e6d15924SDimitry Andric archs: [ armv7, armv7s, arm64 ] # the list of architecture slices that are
71e6d15924SDimitry Andric # supported by this file.
72e6d15924SDimitry Andric uuids: [ armv7:... ] # Optional: List of architecture and UUID pairs.
73e6d15924SDimitry Andric platform: ios # Specifies the platform (macosx, ios, etc)
74e6d15924SDimitry Andric flags: [] # Optional:
75e6d15924SDimitry Andric install-name: /u/l/libfoo.dylib #
76e6d15924SDimitry Andric current-version: 1.2.3 # Optional: defaults to 1.0
77e6d15924SDimitry Andric compatibility-version: 1.0 # Optional: defaults to 1.0
78e6d15924SDimitry Andric swift-version: 0 # Optional: defaults to 0
79e6d15924SDimitry Andric objc-constraint: retain_release # Optional: defaults to retain_release
80e6d15924SDimitry Andric parent-umbrella: # Optional:
81e6d15924SDimitry Andric exports: # List of export sections
82e6d15924SDimitry Andric ...
83e6d15924SDimitry Andric undefineds: # List of undefineds sections
84e6d15924SDimitry Andric ...
85e6d15924SDimitry Andric
86e6d15924SDimitry Andric Each export section is defined as following:
87e6d15924SDimitry Andric
88e6d15924SDimitry Andric - archs: [ arm64 ] # the list of architecture slices
89e6d15924SDimitry Andric allowed-clients: [ client ] # Optional: List of clients
90e6d15924SDimitry Andric re-exports: [ ] # Optional: List of re-exports
91e6d15924SDimitry Andric symbols: [ _sym ] # Optional: List of symbols
92e6d15924SDimitry Andric objc-classes: [] # Optional: List of Objective-C classes
93e6d15924SDimitry Andric objc-ivars: [] # Optional: List of Objective C Instance
94e6d15924SDimitry Andric # Variables
95e6d15924SDimitry Andric weak-def-symbols: [] # Optional: List of weak defined symbols
96e6d15924SDimitry Andric thread-local-symbols: [] # Optional: List of thread local symbols
97e6d15924SDimitry Andric
98e6d15924SDimitry Andric Each undefineds section is defined as following:
99e6d15924SDimitry Andric - archs: [ arm64 ] # the list of architecture slices
100e6d15924SDimitry Andric symbols: [ _sym ] # Optional: List of symbols
101e6d15924SDimitry Andric objc-classes: [] # Optional: List of Objective-C classes
102e6d15924SDimitry Andric objc-ivars: [] # Optional: List of Objective C Instance Variables
103e6d15924SDimitry Andric weak-ref-symbols: [] # Optional: List of weak defined symbols
104e6d15924SDimitry Andric */
105e6d15924SDimitry Andric
106e6d15924SDimitry Andric /*
107e6d15924SDimitry Andric
108e6d15924SDimitry Andric YAML Format specification.
109e6d15924SDimitry Andric
110e6d15924SDimitry Andric --- !tapi-tbd-v3
111e6d15924SDimitry Andric archs: [ armv7, armv7s, arm64 ] # the list of architecture slices that are
112e6d15924SDimitry Andric # supported by this file.
113e6d15924SDimitry Andric uuids: [ armv7:... ] # Optional: List of architecture and UUID pairs.
114e6d15924SDimitry Andric platform: ios # Specifies the platform (macosx, ios, etc)
115e6d15924SDimitry Andric flags: [] # Optional:
116e6d15924SDimitry Andric install-name: /u/l/libfoo.dylib #
117e6d15924SDimitry Andric current-version: 1.2.3 # Optional: defaults to 1.0
118e6d15924SDimitry Andric compatibility-version: 1.0 # Optional: defaults to 1.0
119e6d15924SDimitry Andric swift-abi-version: 0 # Optional: defaults to 0
120e6d15924SDimitry Andric objc-constraint: retain_release # Optional: defaults to retain_release
121e6d15924SDimitry Andric parent-umbrella: # Optional:
122e6d15924SDimitry Andric exports: # List of export sections
123e6d15924SDimitry Andric ...
124e6d15924SDimitry Andric undefineds: # List of undefineds sections
125e6d15924SDimitry Andric ...
126e6d15924SDimitry Andric
127e6d15924SDimitry Andric Each export section is defined as following:
128e6d15924SDimitry Andric
129e6d15924SDimitry Andric - archs: [ arm64 ] # the list of architecture slices
130e6d15924SDimitry Andric allowed-clients: [ client ] # Optional: List of clients
131e6d15924SDimitry Andric re-exports: [ ] # Optional: List of re-exports
132e6d15924SDimitry Andric symbols: [ _sym ] # Optional: List of symbols
133e6d15924SDimitry Andric objc-classes: [] # Optional: List of Objective-C classes
134e6d15924SDimitry Andric objc-eh-types: [] # Optional: List of Objective-C classes
135e6d15924SDimitry Andric # with EH
136e6d15924SDimitry Andric objc-ivars: [] # Optional: List of Objective C Instance
137e6d15924SDimitry Andric # Variables
138e6d15924SDimitry Andric weak-def-symbols: [] # Optional: List of weak defined symbols
139e6d15924SDimitry Andric thread-local-symbols: [] # Optional: List of thread local symbols
140e6d15924SDimitry Andric
141e6d15924SDimitry Andric Each undefineds section is defined as following:
142e6d15924SDimitry Andric - archs: [ arm64 ] # the list of architecture slices
143e6d15924SDimitry Andric symbols: [ _sym ] # Optional: List of symbols
144e6d15924SDimitry Andric objc-classes: [] # Optional: List of Objective-C classes
145e6d15924SDimitry Andric objc-eh-types: [] # Optional: List of Objective-C classes
146e6d15924SDimitry Andric # with EH
147e6d15924SDimitry Andric objc-ivars: [] # Optional: List of Objective C Instance Variables
148e6d15924SDimitry Andric weak-ref-symbols: [] # Optional: List of weak defined symbols
149e6d15924SDimitry Andric */
1501d5ae102SDimitry Andric
1511d5ae102SDimitry Andric /*
1521d5ae102SDimitry Andric
1531d5ae102SDimitry Andric YAML Format specification.
1541d5ae102SDimitry Andric
1551d5ae102SDimitry Andric --- !tapi-tbd
1561d5ae102SDimitry Andric tbd-version: 4 # The tbd version for format
1571d5ae102SDimitry Andric targets: [ armv7-ios, x86_64-maccatalyst ] # The list of applicable tapi supported target triples
1581d5ae102SDimitry Andric uuids: # Optional: List of target and UUID pairs.
1591d5ae102SDimitry Andric - target: armv7-ios
1601d5ae102SDimitry Andric value: ...
1611d5ae102SDimitry Andric - target: x86_64-maccatalyst
1621d5ae102SDimitry Andric value: ...
1631d5ae102SDimitry Andric flags: [] # Optional:
1641d5ae102SDimitry Andric install-name: /u/l/libfoo.dylib #
1651d5ae102SDimitry Andric current-version: 1.2.3 # Optional: defaults to 1.0
1661d5ae102SDimitry Andric compatibility-version: 1.0 # Optional: defaults to 1.0
1671d5ae102SDimitry Andric swift-abi-version: 0 # Optional: defaults to 0
1681d5ae102SDimitry Andric parent-umbrella: # Optional:
1691d5ae102SDimitry Andric allowable-clients:
1701d5ae102SDimitry Andric - targets: [ armv7-ios ] # Optional:
1711d5ae102SDimitry Andric clients: [ clientA ]
1721d5ae102SDimitry Andric exports: # List of export sections
1731d5ae102SDimitry Andric ...
1741d5ae102SDimitry Andric re-exports: # List of reexport sections
1751d5ae102SDimitry Andric ...
1761d5ae102SDimitry Andric undefineds: # List of undefineds sections
1771d5ae102SDimitry Andric ...
1781d5ae102SDimitry Andric
1791d5ae102SDimitry Andric Each export and reexport section is defined as following:
1801d5ae102SDimitry Andric
1811d5ae102SDimitry Andric - targets: [ arm64-macos ] # The list of target triples associated with symbols
1821d5ae102SDimitry Andric symbols: [ _symA ] # Optional: List of symbols
1831d5ae102SDimitry Andric objc-classes: [] # Optional: List of Objective-C classes
1841d5ae102SDimitry Andric objc-eh-types: [] # Optional: List of Objective-C classes
1851d5ae102SDimitry Andric # with EH
1861d5ae102SDimitry Andric objc-ivars: [] # Optional: List of Objective C Instance
1871d5ae102SDimitry Andric # Variables
1881d5ae102SDimitry Andric weak-symbols: [] # Optional: List of weak defined symbols
1891d5ae102SDimitry Andric thread-local-symbols: [] # Optional: List of thread local symbols
1901d5ae102SDimitry Andric - targets: [ arm64-macos, x86_64-maccatalyst ] # Optional: Targets for applicable additional symbols
1911d5ae102SDimitry Andric symbols: [ _symB ] # Optional: List of symbols
1921d5ae102SDimitry Andric
1931d5ae102SDimitry Andric Each undefineds section is defined as following:
1941d5ae102SDimitry Andric - targets: [ arm64-macos ] # The list of target triples associated with symbols
1951d5ae102SDimitry Andric symbols: [ _symC ] # Optional: List of symbols
1961d5ae102SDimitry Andric objc-classes: [] # Optional: List of Objective-C classes
1971d5ae102SDimitry Andric objc-eh-types: [] # Optional: List of Objective-C classes
1981d5ae102SDimitry Andric # with EH
1991d5ae102SDimitry Andric objc-ivars: [] # Optional: List of Objective C Instance Variables
2001d5ae102SDimitry Andric weak-symbols: [] # Optional: List of weak defined symbols
2011d5ae102SDimitry Andric */
202e6d15924SDimitry Andric // clang-format on
203e6d15924SDimitry Andric
204e6d15924SDimitry Andric using namespace llvm;
205e6d15924SDimitry Andric using namespace llvm::yaml;
206e6d15924SDimitry Andric using namespace llvm::MachO;
207e6d15924SDimitry Andric
208e6d15924SDimitry Andric namespace {
209e6d15924SDimitry Andric struct ExportSection {
210e6d15924SDimitry Andric std::vector<Architecture> Architectures;
211e6d15924SDimitry Andric std::vector<FlowStringRef> AllowableClients;
212e6d15924SDimitry Andric std::vector<FlowStringRef> ReexportedLibraries;
213e6d15924SDimitry Andric std::vector<FlowStringRef> Symbols;
214e6d15924SDimitry Andric std::vector<FlowStringRef> Classes;
215e6d15924SDimitry Andric std::vector<FlowStringRef> ClassEHs;
216e6d15924SDimitry Andric std::vector<FlowStringRef> IVars;
217e6d15924SDimitry Andric std::vector<FlowStringRef> WeakDefSymbols;
218e6d15924SDimitry Andric std::vector<FlowStringRef> TLVSymbols;
219e6d15924SDimitry Andric };
220e6d15924SDimitry Andric
221e6d15924SDimitry Andric struct UndefinedSection {
222e6d15924SDimitry Andric std::vector<Architecture> Architectures;
223e6d15924SDimitry Andric std::vector<FlowStringRef> Symbols;
224e6d15924SDimitry Andric std::vector<FlowStringRef> Classes;
225e6d15924SDimitry Andric std::vector<FlowStringRef> ClassEHs;
226e6d15924SDimitry Andric std::vector<FlowStringRef> IVars;
227e6d15924SDimitry Andric std::vector<FlowStringRef> WeakRefSymbols;
228e6d15924SDimitry Andric };
229e6d15924SDimitry Andric
2301d5ae102SDimitry Andric // Sections for direct target mapping in TBDv4
2311d5ae102SDimitry Andric struct SymbolSection {
2321d5ae102SDimitry Andric TargetList Targets;
2331d5ae102SDimitry Andric std::vector<FlowStringRef> Symbols;
2341d5ae102SDimitry Andric std::vector<FlowStringRef> Classes;
2351d5ae102SDimitry Andric std::vector<FlowStringRef> ClassEHs;
2361d5ae102SDimitry Andric std::vector<FlowStringRef> Ivars;
2371d5ae102SDimitry Andric std::vector<FlowStringRef> WeakSymbols;
2381d5ae102SDimitry Andric std::vector<FlowStringRef> TlvSymbols;
2391d5ae102SDimitry Andric };
2401d5ae102SDimitry Andric
2411d5ae102SDimitry Andric struct MetadataSection {
2421d5ae102SDimitry Andric enum Option { Clients, Libraries };
2431d5ae102SDimitry Andric std::vector<Target> Targets;
2441d5ae102SDimitry Andric std::vector<FlowStringRef> Values;
2451d5ae102SDimitry Andric };
2461d5ae102SDimitry Andric
2471d5ae102SDimitry Andric struct UmbrellaSection {
2481d5ae102SDimitry Andric std::vector<Target> Targets;
2491d5ae102SDimitry Andric std::string Umbrella;
2501d5ae102SDimitry Andric };
2511d5ae102SDimitry Andric
2521d5ae102SDimitry Andric // UUID's for TBDv4 are mapped to target not arch
2531d5ae102SDimitry Andric struct UUIDv4 {
2541d5ae102SDimitry Andric Target TargetID;
2551d5ae102SDimitry Andric std::string Value;
2561d5ae102SDimitry Andric
2571d5ae102SDimitry Andric UUIDv4() = default;
UUIDv4__anonfa9f09b60111::UUIDv42581d5ae102SDimitry Andric UUIDv4(const Target &TargetID, const std::string &Value)
2591d5ae102SDimitry Andric : TargetID(TargetID), Value(Value) {}
2601d5ae102SDimitry Andric };
261e6d15924SDimitry Andric } // end anonymous namespace.
262e6d15924SDimitry Andric
263e6d15924SDimitry Andric LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(Architecture)
264e6d15924SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(ExportSection)
265e6d15924SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(UndefinedSection)
2661d5ae102SDimitry Andric // Specific to TBDv4
2671d5ae102SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(SymbolSection)
2681d5ae102SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(MetadataSection)
2691d5ae102SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(UmbrellaSection)
2701d5ae102SDimitry Andric LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(Target)
2711d5ae102SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(UUIDv4)
272e6d15924SDimitry Andric
273e6d15924SDimitry Andric namespace llvm {
274e6d15924SDimitry Andric namespace yaml {
275e6d15924SDimitry Andric
276e6d15924SDimitry Andric template <> struct MappingTraits<ExportSection> {
mappingllvm::yaml::MappingTraits277e6d15924SDimitry Andric static void mapping(IO &IO, ExportSection &Section) {
278e6d15924SDimitry Andric const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
279ac9a064cSDimitry Andric assert((!Ctx || Ctx->FileKind != FileType::Invalid) &&
280e6d15924SDimitry Andric "File type is not set in YAML context");
281e6d15924SDimitry Andric
282e6d15924SDimitry Andric IO.mapRequired("archs", Section.Architectures);
283e6d15924SDimitry Andric if (Ctx->FileKind == FileType::TBD_V1)
284e6d15924SDimitry Andric IO.mapOptional("allowed-clients", Section.AllowableClients);
285e6d15924SDimitry Andric else
286e6d15924SDimitry Andric IO.mapOptional("allowable-clients", Section.AllowableClients);
287e6d15924SDimitry Andric IO.mapOptional("re-exports", Section.ReexportedLibraries);
288e6d15924SDimitry Andric IO.mapOptional("symbols", Section.Symbols);
289e6d15924SDimitry Andric IO.mapOptional("objc-classes", Section.Classes);
290e6d15924SDimitry Andric if (Ctx->FileKind == FileType::TBD_V3)
291e6d15924SDimitry Andric IO.mapOptional("objc-eh-types", Section.ClassEHs);
292e6d15924SDimitry Andric IO.mapOptional("objc-ivars", Section.IVars);
293e6d15924SDimitry Andric IO.mapOptional("weak-def-symbols", Section.WeakDefSymbols);
294e6d15924SDimitry Andric IO.mapOptional("thread-local-symbols", Section.TLVSymbols);
295e6d15924SDimitry Andric }
296e6d15924SDimitry Andric };
297e6d15924SDimitry Andric
298e6d15924SDimitry Andric template <> struct MappingTraits<UndefinedSection> {
mappingllvm::yaml::MappingTraits299e6d15924SDimitry Andric static void mapping(IO &IO, UndefinedSection &Section) {
300e6d15924SDimitry Andric const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
301ac9a064cSDimitry Andric assert((!Ctx || Ctx->FileKind != FileType::Invalid) &&
302e6d15924SDimitry Andric "File type is not set in YAML context");
303e6d15924SDimitry Andric
304e6d15924SDimitry Andric IO.mapRequired("archs", Section.Architectures);
305e6d15924SDimitry Andric IO.mapOptional("symbols", Section.Symbols);
306e6d15924SDimitry Andric IO.mapOptional("objc-classes", Section.Classes);
307e6d15924SDimitry Andric if (Ctx->FileKind == FileType::TBD_V3)
308e6d15924SDimitry Andric IO.mapOptional("objc-eh-types", Section.ClassEHs);
309e6d15924SDimitry Andric IO.mapOptional("objc-ivars", Section.IVars);
310e6d15924SDimitry Andric IO.mapOptional("weak-ref-symbols", Section.WeakRefSymbols);
311e6d15924SDimitry Andric }
312e6d15924SDimitry Andric };
313e6d15924SDimitry Andric
3141d5ae102SDimitry Andric template <> struct MappingTraits<SymbolSection> {
mappingllvm::yaml::MappingTraits3151d5ae102SDimitry Andric static void mapping(IO &IO, SymbolSection &Section) {
3161d5ae102SDimitry Andric IO.mapRequired("targets", Section.Targets);
3171d5ae102SDimitry Andric IO.mapOptional("symbols", Section.Symbols);
3181d5ae102SDimitry Andric IO.mapOptional("objc-classes", Section.Classes);
3191d5ae102SDimitry Andric IO.mapOptional("objc-eh-types", Section.ClassEHs);
3201d5ae102SDimitry Andric IO.mapOptional("objc-ivars", Section.Ivars);
3211d5ae102SDimitry Andric IO.mapOptional("weak-symbols", Section.WeakSymbols);
3221d5ae102SDimitry Andric IO.mapOptional("thread-local-symbols", Section.TlvSymbols);
3231d5ae102SDimitry Andric }
3241d5ae102SDimitry Andric };
3251d5ae102SDimitry Andric
3261d5ae102SDimitry Andric template <> struct MappingTraits<UmbrellaSection> {
mappingllvm::yaml::MappingTraits3271d5ae102SDimitry Andric static void mapping(IO &IO, UmbrellaSection &Section) {
3281d5ae102SDimitry Andric IO.mapRequired("targets", Section.Targets);
3291d5ae102SDimitry Andric IO.mapRequired("umbrella", Section.Umbrella);
3301d5ae102SDimitry Andric }
3311d5ae102SDimitry Andric };
3321d5ae102SDimitry Andric
3331d5ae102SDimitry Andric template <> struct MappingTraits<UUIDv4> {
mappingllvm::yaml::MappingTraits3341d5ae102SDimitry Andric static void mapping(IO &IO, UUIDv4 &UUID) {
3351d5ae102SDimitry Andric IO.mapRequired("target", UUID.TargetID);
3361d5ae102SDimitry Andric IO.mapRequired("value", UUID.Value);
3371d5ae102SDimitry Andric }
3381d5ae102SDimitry Andric };
3391d5ae102SDimitry Andric
3401d5ae102SDimitry Andric template <>
3411d5ae102SDimitry Andric struct MappingContextTraits<MetadataSection, MetadataSection::Option> {
mappingllvm::yaml::MappingContextTraits3421d5ae102SDimitry Andric static void mapping(IO &IO, MetadataSection &Section,
3431d5ae102SDimitry Andric MetadataSection::Option &OptionKind) {
3441d5ae102SDimitry Andric IO.mapRequired("targets", Section.Targets);
3451d5ae102SDimitry Andric switch (OptionKind) {
3461d5ae102SDimitry Andric case MetadataSection::Option::Clients:
3471d5ae102SDimitry Andric IO.mapRequired("clients", Section.Values);
3481d5ae102SDimitry Andric return;
3491d5ae102SDimitry Andric case MetadataSection::Option::Libraries:
3501d5ae102SDimitry Andric IO.mapRequired("libraries", Section.Values);
3511d5ae102SDimitry Andric return;
3521d5ae102SDimitry Andric }
3531d5ae102SDimitry Andric llvm_unreachable("unexpected option for metadata");
3541d5ae102SDimitry Andric }
3551d5ae102SDimitry Andric };
3561d5ae102SDimitry Andric
357e6d15924SDimitry Andric template <> struct ScalarBitSetTraits<TBDFlags> {
bitsetllvm::yaml::ScalarBitSetTraits358e6d15924SDimitry Andric static void bitset(IO &IO, TBDFlags &Flags) {
359e6d15924SDimitry Andric IO.bitSetCase(Flags, "flat_namespace", TBDFlags::FlatNamespace);
360e6d15924SDimitry Andric IO.bitSetCase(Flags, "not_app_extension_safe",
361e6d15924SDimitry Andric TBDFlags::NotApplicationExtensionSafe);
362e6d15924SDimitry Andric IO.bitSetCase(Flags, "installapi", TBDFlags::InstallAPI);
363b1c73532SDimitry Andric IO.bitSetCase(Flags, "not_for_dyld_shared_cache",
364b1c73532SDimitry Andric TBDFlags::OSLibNotForSharedCache);
365e6d15924SDimitry Andric }
366e6d15924SDimitry Andric };
367e6d15924SDimitry Andric
3681d5ae102SDimitry Andric template <> struct ScalarTraits<Target> {
outputllvm::yaml::ScalarTraits3691d5ae102SDimitry Andric static void output(const Target &Value, void *, raw_ostream &OS) {
3701d5ae102SDimitry Andric OS << Value.Arch << "-";
3711d5ae102SDimitry Andric switch (Value.Platform) {
372b1c73532SDimitry Andric #define PLATFORM(platform, id, name, build_name, target, tapi_target, \
373b1c73532SDimitry Andric marketing) \
374b1c73532SDimitry Andric case PLATFORM_##platform: \
375b1c73532SDimitry Andric OS << #tapi_target; \
3761d5ae102SDimitry Andric break;
377b1c73532SDimitry Andric #include "llvm/BinaryFormat/MachO.def"
3781d5ae102SDimitry Andric }
3791d5ae102SDimitry Andric }
3801d5ae102SDimitry Andric
inputllvm::yaml::ScalarTraits3811d5ae102SDimitry Andric static StringRef input(StringRef Scalar, void *, Target &Value) {
3821d5ae102SDimitry Andric auto Result = Target::create(Scalar);
383cfca06d7SDimitry Andric if (!Result) {
384cfca06d7SDimitry Andric consumeError(Result.takeError());
385cfca06d7SDimitry Andric return "unparsable target";
386cfca06d7SDimitry Andric }
3871d5ae102SDimitry Andric
3881d5ae102SDimitry Andric Value = *Result;
3891d5ae102SDimitry Andric if (Value.Arch == AK_unknown)
3901d5ae102SDimitry Andric return "unknown architecture";
3916f8fc217SDimitry Andric if (Value.Platform == PLATFORM_UNKNOWN)
3921d5ae102SDimitry Andric return "unknown platform";
3931d5ae102SDimitry Andric
3941d5ae102SDimitry Andric return {};
3951d5ae102SDimitry Andric }
3961d5ae102SDimitry Andric
mustQuotellvm::yaml::ScalarTraits3971d5ae102SDimitry Andric static QuotingType mustQuote(StringRef) { return QuotingType::None; }
3981d5ae102SDimitry Andric };
3991d5ae102SDimitry Andric
400e6d15924SDimitry Andric template <> struct MappingTraits<const InterfaceFile *> {
401e6d15924SDimitry Andric struct NormalizedTBD {
NormalizedTBDllvm::yaml::MappingTraits::NormalizedTBD402e6d15924SDimitry Andric explicit NormalizedTBD(IO &IO) {}
NormalizedTBDllvm::yaml::MappingTraits::NormalizedTBD403e6d15924SDimitry Andric NormalizedTBD(IO &IO, const InterfaceFile *&File) {
404e6d15924SDimitry Andric Architectures = File->getArchitectures();
4051d5ae102SDimitry Andric Platforms = File->getPlatforms();
406e6d15924SDimitry Andric InstallName = File->getInstallName();
407e6d15924SDimitry Andric CurrentVersion = PackedVersion(File->getCurrentVersion());
408e6d15924SDimitry Andric CompatibilityVersion = PackedVersion(File->getCompatibilityVersion());
409e6d15924SDimitry Andric SwiftABIVersion = File->getSwiftABIVersion();
410e6d15924SDimitry Andric ObjCConstraint = File->getObjCConstraint();
411e6d15924SDimitry Andric
412e6d15924SDimitry Andric Flags = TBDFlags::None;
413e6d15924SDimitry Andric if (!File->isApplicationExtensionSafe())
414e6d15924SDimitry Andric Flags |= TBDFlags::NotApplicationExtensionSafe;
415e6d15924SDimitry Andric
416e6d15924SDimitry Andric if (!File->isTwoLevelNamespace())
417e6d15924SDimitry Andric Flags |= TBDFlags::FlatNamespace;
418e6d15924SDimitry Andric
419cfca06d7SDimitry Andric if (!File->umbrellas().empty())
420cfca06d7SDimitry Andric ParentUmbrella = File->umbrellas().begin()->second;
421e6d15924SDimitry Andric
422e6d15924SDimitry Andric std::set<ArchitectureSet> ArchSet;
423e6d15924SDimitry Andric for (const auto &Library : File->allowableClients())
424e6d15924SDimitry Andric ArchSet.insert(Library.getArchitectures());
425e6d15924SDimitry Andric
426e6d15924SDimitry Andric for (const auto &Library : File->reexportedLibraries())
427e6d15924SDimitry Andric ArchSet.insert(Library.getArchitectures());
428e6d15924SDimitry Andric
429e6d15924SDimitry Andric std::map<const Symbol *, ArchitectureSet> SymbolToArchSet;
4307fa27ce4SDimitry Andric for (const auto *Symbol : File->symbols()) {
431e6d15924SDimitry Andric auto Architectures = Symbol->getArchitectures();
432e6d15924SDimitry Andric SymbolToArchSet[Symbol] = Architectures;
433e6d15924SDimitry Andric ArchSet.insert(Architectures);
434e6d15924SDimitry Andric }
435e6d15924SDimitry Andric
436e6d15924SDimitry Andric for (auto Architectures : ArchSet) {
437e6d15924SDimitry Andric ExportSection Section;
438e6d15924SDimitry Andric Section.Architectures = Architectures;
439e6d15924SDimitry Andric
440e6d15924SDimitry Andric for (const auto &Library : File->allowableClients())
441e6d15924SDimitry Andric if (Library.getArchitectures() == Architectures)
442e6d15924SDimitry Andric Section.AllowableClients.emplace_back(Library.getInstallName());
443e6d15924SDimitry Andric
444e6d15924SDimitry Andric for (const auto &Library : File->reexportedLibraries())
445e6d15924SDimitry Andric if (Library.getArchitectures() == Architectures)
446e6d15924SDimitry Andric Section.ReexportedLibraries.emplace_back(Library.getInstallName());
447e6d15924SDimitry Andric
448e6d15924SDimitry Andric for (const auto &SymArch : SymbolToArchSet) {
449e6d15924SDimitry Andric if (SymArch.second != Architectures)
450e6d15924SDimitry Andric continue;
451e6d15924SDimitry Andric
452e6d15924SDimitry Andric const auto *Symbol = SymArch.first;
453e6d15924SDimitry Andric switch (Symbol->getKind()) {
454ac9a064cSDimitry Andric case EncodeKind::GlobalSymbol:
455e6d15924SDimitry Andric if (Symbol->isWeakDefined())
456e6d15924SDimitry Andric Section.WeakDefSymbols.emplace_back(Symbol->getName());
457e6d15924SDimitry Andric else if (Symbol->isThreadLocalValue())
458e6d15924SDimitry Andric Section.TLVSymbols.emplace_back(Symbol->getName());
459e6d15924SDimitry Andric else
460e6d15924SDimitry Andric Section.Symbols.emplace_back(Symbol->getName());
461e6d15924SDimitry Andric break;
462ac9a064cSDimitry Andric case EncodeKind::ObjectiveCClass:
463e6d15924SDimitry Andric if (File->getFileType() != FileType::TBD_V3)
464e6d15924SDimitry Andric Section.Classes.emplace_back(
465e6d15924SDimitry Andric copyString("_" + Symbol->getName().str()));
466e6d15924SDimitry Andric else
467e6d15924SDimitry Andric Section.Classes.emplace_back(Symbol->getName());
468e6d15924SDimitry Andric break;
469ac9a064cSDimitry Andric case EncodeKind::ObjectiveCClassEHType:
470e6d15924SDimitry Andric if (File->getFileType() != FileType::TBD_V3)
471e6d15924SDimitry Andric Section.Symbols.emplace_back(
472e6d15924SDimitry Andric copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str()));
473e6d15924SDimitry Andric else
474e6d15924SDimitry Andric Section.ClassEHs.emplace_back(Symbol->getName());
475e6d15924SDimitry Andric break;
476ac9a064cSDimitry Andric case EncodeKind::ObjectiveCInstanceVariable:
477e6d15924SDimitry Andric if (File->getFileType() != FileType::TBD_V3)
478e6d15924SDimitry Andric Section.IVars.emplace_back(
479e6d15924SDimitry Andric copyString("_" + Symbol->getName().str()));
480e6d15924SDimitry Andric else
481e6d15924SDimitry Andric Section.IVars.emplace_back(Symbol->getName());
482e6d15924SDimitry Andric break;
483e6d15924SDimitry Andric }
484e6d15924SDimitry Andric }
485b60736ecSDimitry Andric llvm::sort(Section.Symbols);
486b60736ecSDimitry Andric llvm::sort(Section.Classes);
487b60736ecSDimitry Andric llvm::sort(Section.ClassEHs);
488b60736ecSDimitry Andric llvm::sort(Section.IVars);
489b60736ecSDimitry Andric llvm::sort(Section.WeakDefSymbols);
490b60736ecSDimitry Andric llvm::sort(Section.TLVSymbols);
491e6d15924SDimitry Andric Exports.emplace_back(std::move(Section));
492e6d15924SDimitry Andric }
493e6d15924SDimitry Andric
494e6d15924SDimitry Andric ArchSet.clear();
495e6d15924SDimitry Andric SymbolToArchSet.clear();
496e6d15924SDimitry Andric
497e6d15924SDimitry Andric for (const auto *Symbol : File->undefineds()) {
498e6d15924SDimitry Andric auto Architectures = Symbol->getArchitectures();
499e6d15924SDimitry Andric SymbolToArchSet[Symbol] = Architectures;
500e6d15924SDimitry Andric ArchSet.insert(Architectures);
501e6d15924SDimitry Andric }
502e6d15924SDimitry Andric
503e6d15924SDimitry Andric for (auto Architectures : ArchSet) {
504e6d15924SDimitry Andric UndefinedSection Section;
505e6d15924SDimitry Andric Section.Architectures = Architectures;
506e6d15924SDimitry Andric
507e6d15924SDimitry Andric for (const auto &SymArch : SymbolToArchSet) {
508e6d15924SDimitry Andric if (SymArch.second != Architectures)
509e6d15924SDimitry Andric continue;
510e6d15924SDimitry Andric
511e6d15924SDimitry Andric const auto *Symbol = SymArch.first;
512e6d15924SDimitry Andric switch (Symbol->getKind()) {
513ac9a064cSDimitry Andric case EncodeKind::GlobalSymbol:
514e6d15924SDimitry Andric if (Symbol->isWeakReferenced())
515e6d15924SDimitry Andric Section.WeakRefSymbols.emplace_back(Symbol->getName());
516e6d15924SDimitry Andric else
517e6d15924SDimitry Andric Section.Symbols.emplace_back(Symbol->getName());
518e6d15924SDimitry Andric break;
519ac9a064cSDimitry Andric case EncodeKind::ObjectiveCClass:
520e6d15924SDimitry Andric if (File->getFileType() != FileType::TBD_V3)
521e6d15924SDimitry Andric Section.Classes.emplace_back(
522e6d15924SDimitry Andric copyString("_" + Symbol->getName().str()));
523e6d15924SDimitry Andric else
524e6d15924SDimitry Andric Section.Classes.emplace_back(Symbol->getName());
525e6d15924SDimitry Andric break;
526ac9a064cSDimitry Andric case EncodeKind::ObjectiveCClassEHType:
527e6d15924SDimitry Andric if (File->getFileType() != FileType::TBD_V3)
528e6d15924SDimitry Andric Section.Symbols.emplace_back(
529e6d15924SDimitry Andric copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str()));
530e6d15924SDimitry Andric else
531e6d15924SDimitry Andric Section.ClassEHs.emplace_back(Symbol->getName());
532e6d15924SDimitry Andric break;
533ac9a064cSDimitry Andric case EncodeKind::ObjectiveCInstanceVariable:
534e6d15924SDimitry Andric if (File->getFileType() != FileType::TBD_V3)
535e6d15924SDimitry Andric Section.IVars.emplace_back(
536e6d15924SDimitry Andric copyString("_" + Symbol->getName().str()));
537e6d15924SDimitry Andric else
538e6d15924SDimitry Andric Section.IVars.emplace_back(Symbol->getName());
539e6d15924SDimitry Andric break;
540e6d15924SDimitry Andric }
541e6d15924SDimitry Andric }
542b60736ecSDimitry Andric llvm::sort(Section.Symbols);
543b60736ecSDimitry Andric llvm::sort(Section.Classes);
544b60736ecSDimitry Andric llvm::sort(Section.ClassEHs);
545b60736ecSDimitry Andric llvm::sort(Section.IVars);
546b60736ecSDimitry Andric llvm::sort(Section.WeakRefSymbols);
547e6d15924SDimitry Andric Undefineds.emplace_back(std::move(Section));
548e6d15924SDimitry Andric }
549e6d15924SDimitry Andric }
550e6d15924SDimitry Andric
5511d5ae102SDimitry Andric // TBD v1 - TBD v3 files only support one platform and several
5521d5ae102SDimitry Andric // architectures. It is possible to have more than one platform for TBD v3
5531d5ae102SDimitry Andric // files, but the architectures don't apply to all
5541d5ae102SDimitry Andric // platforms, specifically to filter out the i386 slice from
5551d5ae102SDimitry Andric // platform macCatalyst.
synthesizeTargetsllvm::yaml::MappingTraits::NormalizedTBD5561d5ae102SDimitry Andric TargetList synthesizeTargets(ArchitectureSet Architectures,
5571d5ae102SDimitry Andric const PlatformSet &Platforms) {
5581d5ae102SDimitry Andric TargetList Targets;
5591d5ae102SDimitry Andric
5601d5ae102SDimitry Andric for (auto Platform : Platforms) {
5616f8fc217SDimitry Andric Platform = mapToPlatformType(Platform, Architectures.hasX86());
5621d5ae102SDimitry Andric
5631d5ae102SDimitry Andric for (const auto &&Architecture : Architectures) {
5646f8fc217SDimitry Andric if ((Architecture == AK_i386) && (Platform == PLATFORM_MACCATALYST))
5651d5ae102SDimitry Andric continue;
5661d5ae102SDimitry Andric
5671d5ae102SDimitry Andric Targets.emplace_back(Architecture, Platform);
5681d5ae102SDimitry Andric }
5691d5ae102SDimitry Andric }
5701d5ae102SDimitry Andric return Targets;
5711d5ae102SDimitry Andric }
5721d5ae102SDimitry Andric
denormalizellvm::yaml::MappingTraits::NormalizedTBD573e6d15924SDimitry Andric const InterfaceFile *denormalize(IO &IO) {
574e6d15924SDimitry Andric auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
575e6d15924SDimitry Andric assert(Ctx);
576e6d15924SDimitry Andric
577e6d15924SDimitry Andric auto *File = new InterfaceFile;
578e6d15924SDimitry Andric File->setPath(Ctx->Path);
579e6d15924SDimitry Andric File->setFileType(Ctx->FileKind);
5801d5ae102SDimitry Andric File->addTargets(synthesizeTargets(Architectures, Platforms));
581e6d15924SDimitry Andric File->setInstallName(InstallName);
582e6d15924SDimitry Andric File->setCurrentVersion(CurrentVersion);
583e6d15924SDimitry Andric File->setCompatibilityVersion(CompatibilityVersion);
584e6d15924SDimitry Andric File->setSwiftABIVersion(SwiftABIVersion);
585e6d15924SDimitry Andric File->setObjCConstraint(ObjCConstraint);
5861d5ae102SDimitry Andric for (const auto &Target : File->targets())
5871d5ae102SDimitry Andric File->addParentUmbrella(Target, ParentUmbrella);
588e6d15924SDimitry Andric
589e6d15924SDimitry Andric if (Ctx->FileKind == FileType::TBD_V1) {
590e6d15924SDimitry Andric File->setTwoLevelNamespace();
591e6d15924SDimitry Andric File->setApplicationExtensionSafe();
592e6d15924SDimitry Andric } else {
593e6d15924SDimitry Andric File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
594e6d15924SDimitry Andric File->setApplicationExtensionSafe(
595e6d15924SDimitry Andric !(Flags & TBDFlags::NotApplicationExtensionSafe));
596e6d15924SDimitry Andric }
597e6d15924SDimitry Andric
598b1c73532SDimitry Andric // For older file formats, the segment where the symbol
599b1c73532SDimitry Andric // comes from is unknown, treat all symbols as Data
600b1c73532SDimitry Andric // in these cases.
601b1c73532SDimitry Andric const auto Flags = SymbolFlags::Data;
602b1c73532SDimitry Andric
603e6d15924SDimitry Andric for (const auto &Section : Exports) {
6041d5ae102SDimitry Andric const auto Targets =
6051d5ae102SDimitry Andric synthesizeTargets(Section.Architectures, Platforms);
6061d5ae102SDimitry Andric
6071d5ae102SDimitry Andric for (const auto &Lib : Section.AllowableClients)
6081d5ae102SDimitry Andric for (const auto &Target : Targets)
6091d5ae102SDimitry Andric File->addAllowableClient(Lib, Target);
6101d5ae102SDimitry Andric
6111d5ae102SDimitry Andric for (const auto &Lib : Section.ReexportedLibraries)
6121d5ae102SDimitry Andric for (const auto &Target : Targets)
6131d5ae102SDimitry Andric File->addReexportedLibrary(Lib, Target);
614e6d15924SDimitry Andric
615e6d15924SDimitry Andric for (const auto &Symbol : Section.Symbols) {
616e6d15924SDimitry Andric if (Ctx->FileKind != FileType::TBD_V3 &&
617312c0ed1SDimitry Andric Symbol.value.starts_with(ObjC2EHTypePrefix))
618ac9a064cSDimitry Andric File->addSymbol(EncodeKind::ObjectiveCClassEHType,
619b1c73532SDimitry Andric Symbol.value.drop_front(15), Targets, Flags);
620e6d15924SDimitry Andric else
621ac9a064cSDimitry Andric File->addSymbol(EncodeKind::GlobalSymbol, Symbol, Targets, Flags);
622e6d15924SDimitry Andric }
623e6d15924SDimitry Andric for (auto &Symbol : Section.Classes) {
624e6d15924SDimitry Andric auto Name = Symbol.value;
625e6d15924SDimitry Andric if (Ctx->FileKind != FileType::TBD_V3)
626e6d15924SDimitry Andric Name = Name.drop_front();
627ac9a064cSDimitry Andric File->addSymbol(EncodeKind::ObjectiveCClass, Name, Targets, Flags);
628e6d15924SDimitry Andric }
629e6d15924SDimitry Andric for (auto &Symbol : Section.ClassEHs)
630ac9a064cSDimitry Andric File->addSymbol(EncodeKind::ObjectiveCClassEHType, Symbol, Targets,
631b1c73532SDimitry Andric Flags);
632e6d15924SDimitry Andric for (auto &Symbol : Section.IVars) {
633e6d15924SDimitry Andric auto Name = Symbol.value;
634e6d15924SDimitry Andric if (Ctx->FileKind != FileType::TBD_V3)
635e6d15924SDimitry Andric Name = Name.drop_front();
636ac9a064cSDimitry Andric File->addSymbol(EncodeKind::ObjectiveCInstanceVariable, Name, Targets,
637b1c73532SDimitry Andric Flags);
638e6d15924SDimitry Andric }
639e6d15924SDimitry Andric for (auto &Symbol : Section.WeakDefSymbols)
640ac9a064cSDimitry Andric File->addSymbol(EncodeKind::GlobalSymbol, Symbol, Targets,
641b1c73532SDimitry Andric SymbolFlags::WeakDefined | Flags);
642e6d15924SDimitry Andric for (auto &Symbol : Section.TLVSymbols)
643ac9a064cSDimitry Andric File->addSymbol(EncodeKind::GlobalSymbol, Symbol, Targets,
644b1c73532SDimitry Andric SymbolFlags::ThreadLocalValue | Flags);
645e6d15924SDimitry Andric }
646e6d15924SDimitry Andric
647e6d15924SDimitry Andric for (const auto &Section : Undefineds) {
6481d5ae102SDimitry Andric const auto Targets =
6491d5ae102SDimitry Andric synthesizeTargets(Section.Architectures, Platforms);
650e6d15924SDimitry Andric for (auto &Symbol : Section.Symbols) {
651e6d15924SDimitry Andric if (Ctx->FileKind != FileType::TBD_V3 &&
652312c0ed1SDimitry Andric Symbol.value.starts_with(ObjC2EHTypePrefix))
653ac9a064cSDimitry Andric File->addSymbol(EncodeKind::ObjectiveCClassEHType,
6541d5ae102SDimitry Andric Symbol.value.drop_front(15), Targets,
655b1c73532SDimitry Andric SymbolFlags::Undefined | Flags);
656e6d15924SDimitry Andric else
657ac9a064cSDimitry Andric File->addSymbol(EncodeKind::GlobalSymbol, Symbol, Targets,
658b1c73532SDimitry Andric SymbolFlags::Undefined | Flags);
659e6d15924SDimitry Andric }
660e6d15924SDimitry Andric for (auto &Symbol : Section.Classes) {
661e6d15924SDimitry Andric auto Name = Symbol.value;
662e6d15924SDimitry Andric if (Ctx->FileKind != FileType::TBD_V3)
663e6d15924SDimitry Andric Name = Name.drop_front();
664ac9a064cSDimitry Andric File->addSymbol(EncodeKind::ObjectiveCClass, Name, Targets,
665b1c73532SDimitry Andric SymbolFlags::Undefined | Flags);
666e6d15924SDimitry Andric }
667e6d15924SDimitry Andric for (auto &Symbol : Section.ClassEHs)
668ac9a064cSDimitry Andric File->addSymbol(EncodeKind::ObjectiveCClassEHType, Symbol, Targets,
669b1c73532SDimitry Andric SymbolFlags::Undefined | Flags);
670e6d15924SDimitry Andric for (auto &Symbol : Section.IVars) {
671e6d15924SDimitry Andric auto Name = Symbol.value;
672e6d15924SDimitry Andric if (Ctx->FileKind != FileType::TBD_V3)
673e6d15924SDimitry Andric Name = Name.drop_front();
674ac9a064cSDimitry Andric File->addSymbol(EncodeKind::ObjectiveCInstanceVariable, Name, Targets,
675b1c73532SDimitry Andric SymbolFlags::Undefined | Flags);
676e6d15924SDimitry Andric }
677e6d15924SDimitry Andric for (auto &Symbol : Section.WeakRefSymbols)
678ac9a064cSDimitry Andric File->addSymbol(EncodeKind::GlobalSymbol, Symbol, Targets,
679b1c73532SDimitry Andric SymbolFlags::Undefined | SymbolFlags::WeakReferenced |
680b1c73532SDimitry Andric Flags);
681e6d15924SDimitry Andric }
682e6d15924SDimitry Andric
683e6d15924SDimitry Andric return File;
684e6d15924SDimitry Andric }
685e6d15924SDimitry Andric
686e6d15924SDimitry Andric llvm::BumpPtrAllocator Allocator;
copyStringllvm::yaml::MappingTraits::NormalizedTBD687e6d15924SDimitry Andric StringRef copyString(StringRef String) {
688e6d15924SDimitry Andric if (String.empty())
689e6d15924SDimitry Andric return {};
690e6d15924SDimitry Andric
691e6d15924SDimitry Andric void *Ptr = Allocator.Allocate(String.size(), 1);
692e6d15924SDimitry Andric memcpy(Ptr, String.data(), String.size());
693e6d15924SDimitry Andric return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
694e6d15924SDimitry Andric }
695e6d15924SDimitry Andric
696e6d15924SDimitry Andric std::vector<Architecture> Architectures;
697e6d15924SDimitry Andric std::vector<UUID> UUIDs;
6981d5ae102SDimitry Andric PlatformSet Platforms;
699e6d15924SDimitry Andric StringRef InstallName;
700e6d15924SDimitry Andric PackedVersion CurrentVersion;
701e6d15924SDimitry Andric PackedVersion CompatibilityVersion;
702e6d15924SDimitry Andric SwiftVersion SwiftABIVersion{0};
703e6d15924SDimitry Andric ObjCConstraintType ObjCConstraint{ObjCConstraintType::None};
704e6d15924SDimitry Andric TBDFlags Flags{TBDFlags::None};
705e6d15924SDimitry Andric StringRef ParentUmbrella;
706e6d15924SDimitry Andric std::vector<ExportSection> Exports;
707e6d15924SDimitry Andric std::vector<UndefinedSection> Undefineds;
708e6d15924SDimitry Andric };
709e6d15924SDimitry Andric
setFileTypeForInputllvm::yaml::MappingTraits7101d5ae102SDimitry Andric static void setFileTypeForInput(TextAPIContext *Ctx, IO &IO) {
7111d5ae102SDimitry Andric if (IO.mapTag("!tapi-tbd", false))
7121d5ae102SDimitry Andric Ctx->FileKind = FileType::TBD_V4;
713e6d15924SDimitry Andric else if (IO.mapTag("!tapi-tbd-v3", false))
7141d5ae102SDimitry Andric Ctx->FileKind = FileType::TBD_V3;
7151d5ae102SDimitry Andric else if (IO.mapTag("!tapi-tbd-v2", false))
716e6d15924SDimitry Andric Ctx->FileKind = FileType::TBD_V2;
717e6d15924SDimitry Andric else if (IO.mapTag("!tapi-tbd-v1", false) ||
718e6d15924SDimitry Andric IO.mapTag("tag:yaml.org,2002:map", false))
719e6d15924SDimitry Andric Ctx->FileKind = FileType::TBD_V1;
720e6d15924SDimitry Andric else {
7211d5ae102SDimitry Andric Ctx->FileKind = FileType::Invalid;
722e6d15924SDimitry Andric return;
723e6d15924SDimitry Andric }
724e6d15924SDimitry Andric }
725e6d15924SDimitry Andric
mappingllvm::yaml::MappingTraits7261d5ae102SDimitry Andric static void mapping(IO &IO, const InterfaceFile *&File) {
7271d5ae102SDimitry Andric auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
7281d5ae102SDimitry Andric assert((!Ctx || !IO.outputting() ||
7291d5ae102SDimitry Andric (Ctx && Ctx->FileKind != FileType::Invalid)) &&
7301d5ae102SDimitry Andric "File type is not set in YAML context");
7311d5ae102SDimitry Andric
7321d5ae102SDimitry Andric if (!IO.outputting()) {
7331d5ae102SDimitry Andric setFileTypeForInput(Ctx, IO);
7341d5ae102SDimitry Andric switch (Ctx->FileKind) {
7351d5ae102SDimitry Andric default:
7361d5ae102SDimitry Andric break;
7371d5ae102SDimitry Andric case FileType::TBD_V4:
7381d5ae102SDimitry Andric mapKeysToValuesV4(IO, File);
7391d5ae102SDimitry Andric return;
7401d5ae102SDimitry Andric case FileType::Invalid:
7411d5ae102SDimitry Andric IO.setError("unsupported file type");
7421d5ae102SDimitry Andric return;
7431d5ae102SDimitry Andric }
7441d5ae102SDimitry Andric } else {
7451d5ae102SDimitry Andric // Set file type when writing.
746e6d15924SDimitry Andric switch (Ctx->FileKind) {
747e6d15924SDimitry Andric default:
748e6d15924SDimitry Andric llvm_unreachable("unexpected file type");
7491d5ae102SDimitry Andric case FileType::TBD_V4:
7501d5ae102SDimitry Andric mapKeysToValuesV4(IO, File);
7511d5ae102SDimitry Andric return;
7521d5ae102SDimitry Andric case FileType::TBD_V3:
7531d5ae102SDimitry Andric IO.mapTag("!tapi-tbd-v3", true);
754e6d15924SDimitry Andric break;
755e6d15924SDimitry Andric case FileType::TBD_V2:
756e6d15924SDimitry Andric IO.mapTag("!tapi-tbd-v2", true);
757e6d15924SDimitry Andric break;
7581d5ae102SDimitry Andric case FileType::TBD_V1:
7591d5ae102SDimitry Andric // Don't write the tag into the .tbd file for TBD v1
760e6d15924SDimitry Andric break;
761e6d15924SDimitry Andric }
762e6d15924SDimitry Andric }
7631d5ae102SDimitry Andric mapKeysToValues(Ctx->FileKind, IO, File);
7641d5ae102SDimitry Andric }
765e6d15924SDimitry Andric
7661d5ae102SDimitry Andric using SectionList = std::vector<SymbolSection>;
7671d5ae102SDimitry Andric struct NormalizedTBD_V4 {
NormalizedTBD_V4llvm::yaml::MappingTraits::NormalizedTBD_V47681d5ae102SDimitry Andric explicit NormalizedTBD_V4(IO &IO) {}
NormalizedTBD_V4llvm::yaml::MappingTraits::NormalizedTBD_V47691d5ae102SDimitry Andric NormalizedTBD_V4(IO &IO, const InterfaceFile *&File) {
7701d5ae102SDimitry Andric auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
7711d5ae102SDimitry Andric assert(Ctx);
772b1c73532SDimitry Andric TBDVersion = Ctx->FileKind >> 4;
7731d5ae102SDimitry Andric Targets.insert(Targets.begin(), File->targets().begin(),
7741d5ae102SDimitry Andric File->targets().end());
7751d5ae102SDimitry Andric InstallName = File->getInstallName();
7761d5ae102SDimitry Andric CurrentVersion = File->getCurrentVersion();
7771d5ae102SDimitry Andric CompatibilityVersion = File->getCompatibilityVersion();
7781d5ae102SDimitry Andric SwiftABIVersion = File->getSwiftABIVersion();
7791d5ae102SDimitry Andric
7801d5ae102SDimitry Andric Flags = TBDFlags::None;
7811d5ae102SDimitry Andric if (!File->isApplicationExtensionSafe())
7821d5ae102SDimitry Andric Flags |= TBDFlags::NotApplicationExtensionSafe;
7831d5ae102SDimitry Andric
7841d5ae102SDimitry Andric if (!File->isTwoLevelNamespace())
7851d5ae102SDimitry Andric Flags |= TBDFlags::FlatNamespace;
7861d5ae102SDimitry Andric
787b1c73532SDimitry Andric if (File->isOSLibNotForSharedCache())
788b1c73532SDimitry Andric Flags |= TBDFlags::OSLibNotForSharedCache;
789b1c73532SDimitry Andric
7901d5ae102SDimitry Andric {
7911d5ae102SDimitry Andric std::map<std::string, TargetList> valueToTargetList;
7921d5ae102SDimitry Andric for (const auto &it : File->umbrellas())
7931d5ae102SDimitry Andric valueToTargetList[it.second].emplace_back(it.first);
7941d5ae102SDimitry Andric
7951d5ae102SDimitry Andric for (const auto &it : valueToTargetList) {
7961d5ae102SDimitry Andric UmbrellaSection CurrentSection;
7971d5ae102SDimitry Andric CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
7981d5ae102SDimitry Andric it.second.begin(), it.second.end());
7991d5ae102SDimitry Andric CurrentSection.Umbrella = it.first;
8001d5ae102SDimitry Andric ParentUmbrellas.emplace_back(std::move(CurrentSection));
8011d5ae102SDimitry Andric }
8021d5ae102SDimitry Andric }
8031d5ae102SDimitry Andric
8041d5ae102SDimitry Andric assignTargetsToLibrary(File->allowableClients(), AllowableClients);
8051d5ae102SDimitry Andric assignTargetsToLibrary(File->reexportedLibraries(), ReexportedLibraries);
8061d5ae102SDimitry Andric
8071d5ae102SDimitry Andric auto handleSymbols =
8081d5ae102SDimitry Andric [](SectionList &CurrentSections,
8097fa27ce4SDimitry Andric InterfaceFile::const_filtered_symbol_range Symbols) {
8101d5ae102SDimitry Andric std::set<TargetList> TargetSet;
8111d5ae102SDimitry Andric std::map<const Symbol *, TargetList> SymbolToTargetList;
8121d5ae102SDimitry Andric for (const auto *Symbol : Symbols) {
8131d5ae102SDimitry Andric TargetList Targets(Symbol->targets());
8141d5ae102SDimitry Andric SymbolToTargetList[Symbol] = Targets;
8151d5ae102SDimitry Andric TargetSet.emplace(std::move(Targets));
8161d5ae102SDimitry Andric }
8171d5ae102SDimitry Andric for (const auto &TargetIDs : TargetSet) {
8181d5ae102SDimitry Andric SymbolSection CurrentSection;
8191d5ae102SDimitry Andric CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
8201d5ae102SDimitry Andric TargetIDs.begin(), TargetIDs.end());
8211d5ae102SDimitry Andric
8221d5ae102SDimitry Andric for (const auto &IT : SymbolToTargetList) {
8231d5ae102SDimitry Andric if (IT.second != TargetIDs)
8241d5ae102SDimitry Andric continue;
8251d5ae102SDimitry Andric
8261d5ae102SDimitry Andric const auto *Symbol = IT.first;
8271d5ae102SDimitry Andric switch (Symbol->getKind()) {
828ac9a064cSDimitry Andric case EncodeKind::GlobalSymbol:
8291d5ae102SDimitry Andric if (Symbol->isWeakDefined())
8301d5ae102SDimitry Andric CurrentSection.WeakSymbols.emplace_back(Symbol->getName());
8311d5ae102SDimitry Andric else if (Symbol->isThreadLocalValue())
8321d5ae102SDimitry Andric CurrentSection.TlvSymbols.emplace_back(Symbol->getName());
8331d5ae102SDimitry Andric else
8341d5ae102SDimitry Andric CurrentSection.Symbols.emplace_back(Symbol->getName());
8351d5ae102SDimitry Andric break;
836ac9a064cSDimitry Andric case EncodeKind::ObjectiveCClass:
8371d5ae102SDimitry Andric CurrentSection.Classes.emplace_back(Symbol->getName());
8381d5ae102SDimitry Andric break;
839ac9a064cSDimitry Andric case EncodeKind::ObjectiveCClassEHType:
8401d5ae102SDimitry Andric CurrentSection.ClassEHs.emplace_back(Symbol->getName());
8411d5ae102SDimitry Andric break;
842ac9a064cSDimitry Andric case EncodeKind::ObjectiveCInstanceVariable:
8431d5ae102SDimitry Andric CurrentSection.Ivars.emplace_back(Symbol->getName());
8441d5ae102SDimitry Andric break;
8451d5ae102SDimitry Andric }
8461d5ae102SDimitry Andric }
8471d5ae102SDimitry Andric sort(CurrentSection.Symbols);
8481d5ae102SDimitry Andric sort(CurrentSection.Classes);
8491d5ae102SDimitry Andric sort(CurrentSection.ClassEHs);
8501d5ae102SDimitry Andric sort(CurrentSection.Ivars);
8511d5ae102SDimitry Andric sort(CurrentSection.WeakSymbols);
8521d5ae102SDimitry Andric sort(CurrentSection.TlvSymbols);
8531d5ae102SDimitry Andric CurrentSections.emplace_back(std::move(CurrentSection));
8541d5ae102SDimitry Andric }
8551d5ae102SDimitry Andric };
8561d5ae102SDimitry Andric
8577fa27ce4SDimitry Andric handleSymbols(Exports, File->exports());
8587fa27ce4SDimitry Andric handleSymbols(Reexports, File->reexports());
8597fa27ce4SDimitry Andric handleSymbols(Undefineds, File->undefineds());
8601d5ae102SDimitry Andric }
8611d5ae102SDimitry Andric
denormalizellvm::yaml::MappingTraits::NormalizedTBD_V48621d5ae102SDimitry Andric const InterfaceFile *denormalize(IO &IO) {
8631d5ae102SDimitry Andric auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
8641d5ae102SDimitry Andric assert(Ctx);
8651d5ae102SDimitry Andric
8661d5ae102SDimitry Andric auto *File = new InterfaceFile;
8671d5ae102SDimitry Andric File->setPath(Ctx->Path);
8681d5ae102SDimitry Andric File->setFileType(Ctx->FileKind);
8691d5ae102SDimitry Andric File->addTargets(Targets);
8701d5ae102SDimitry Andric File->setInstallName(InstallName);
8711d5ae102SDimitry Andric File->setCurrentVersion(CurrentVersion);
8721d5ae102SDimitry Andric File->setCompatibilityVersion(CompatibilityVersion);
8731d5ae102SDimitry Andric File->setSwiftABIVersion(SwiftABIVersion);
8741d5ae102SDimitry Andric for (const auto &CurrentSection : ParentUmbrellas)
8751d5ae102SDimitry Andric for (const auto &target : CurrentSection.Targets)
8761d5ae102SDimitry Andric File->addParentUmbrella(target, CurrentSection.Umbrella);
8771d5ae102SDimitry Andric File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
8781d5ae102SDimitry Andric File->setApplicationExtensionSafe(
8791d5ae102SDimitry Andric !(Flags & TBDFlags::NotApplicationExtensionSafe));
880b1c73532SDimitry Andric File->setOSLibNotForSharedCache(
881b1c73532SDimitry Andric (Flags & TBDFlags::OSLibNotForSharedCache));
8821d5ae102SDimitry Andric
8831d5ae102SDimitry Andric for (const auto &CurrentSection : AllowableClients) {
8841d5ae102SDimitry Andric for (const auto &lib : CurrentSection.Values)
8851d5ae102SDimitry Andric for (const auto &Target : CurrentSection.Targets)
8861d5ae102SDimitry Andric File->addAllowableClient(lib, Target);
8871d5ae102SDimitry Andric }
8881d5ae102SDimitry Andric
8891d5ae102SDimitry Andric for (const auto &CurrentSection : ReexportedLibraries) {
8901d5ae102SDimitry Andric for (const auto &Lib : CurrentSection.Values)
8911d5ae102SDimitry Andric for (const auto &Target : CurrentSection.Targets)
8921d5ae102SDimitry Andric File->addReexportedLibrary(Lib, Target);
8931d5ae102SDimitry Andric }
8941d5ae102SDimitry Andric
8951d5ae102SDimitry Andric auto handleSymbols = [File](const SectionList &CurrentSections,
896b1c73532SDimitry Andric SymbolFlags InputFlag = SymbolFlags::None) {
897b1c73532SDimitry Andric // For older file formats, the segment where the symbol
898b1c73532SDimitry Andric // comes from is unknown, treat all symbols as Data
899b1c73532SDimitry Andric // in these cases.
900b1c73532SDimitry Andric const SymbolFlags Flag = InputFlag | SymbolFlags::Data;
901b1c73532SDimitry Andric
9021d5ae102SDimitry Andric for (const auto &CurrentSection : CurrentSections) {
9031d5ae102SDimitry Andric for (auto &sym : CurrentSection.Symbols)
904ac9a064cSDimitry Andric File->addSymbol(EncodeKind::GlobalSymbol, sym,
9051d5ae102SDimitry Andric CurrentSection.Targets, Flag);
9061d5ae102SDimitry Andric
9071d5ae102SDimitry Andric for (auto &sym : CurrentSection.Classes)
908ac9a064cSDimitry Andric File->addSymbol(EncodeKind::ObjectiveCClass, sym,
9097fa27ce4SDimitry Andric CurrentSection.Targets, Flag);
9101d5ae102SDimitry Andric
9111d5ae102SDimitry Andric for (auto &sym : CurrentSection.ClassEHs)
912ac9a064cSDimitry Andric File->addSymbol(EncodeKind::ObjectiveCClassEHType, sym,
9137fa27ce4SDimitry Andric CurrentSection.Targets, Flag);
9141d5ae102SDimitry Andric
9151d5ae102SDimitry Andric for (auto &sym : CurrentSection.Ivars)
916ac9a064cSDimitry Andric File->addSymbol(EncodeKind::ObjectiveCInstanceVariable, sym,
9177fa27ce4SDimitry Andric CurrentSection.Targets, Flag);
9181d5ae102SDimitry Andric
919b1c73532SDimitry Andric SymbolFlags SymFlag =
920b1c73532SDimitry Andric ((Flag & SymbolFlags::Undefined) == SymbolFlags::Undefined)
9217fa27ce4SDimitry Andric ? SymbolFlags::WeakReferenced
9227fa27ce4SDimitry Andric : SymbolFlags::WeakDefined;
9237fa27ce4SDimitry Andric for (auto &sym : CurrentSection.WeakSymbols) {
924ac9a064cSDimitry Andric File->addSymbol(EncodeKind::GlobalSymbol, sym,
9257fa27ce4SDimitry Andric CurrentSection.Targets, Flag | SymFlag);
9267fa27ce4SDimitry Andric }
927cfca06d7SDimitry Andric
9281d5ae102SDimitry Andric for (auto &sym : CurrentSection.TlvSymbols)
929ac9a064cSDimitry Andric File->addSymbol(EncodeKind::GlobalSymbol, sym,
9301d5ae102SDimitry Andric CurrentSection.Targets,
9317fa27ce4SDimitry Andric Flag | SymbolFlags::ThreadLocalValue);
9321d5ae102SDimitry Andric }
9331d5ae102SDimitry Andric };
9341d5ae102SDimitry Andric
9351d5ae102SDimitry Andric handleSymbols(Exports);
9361d5ae102SDimitry Andric handleSymbols(Reexports, SymbolFlags::Rexported);
9371d5ae102SDimitry Andric handleSymbols(Undefineds, SymbolFlags::Undefined);
9381d5ae102SDimitry Andric
9391d5ae102SDimitry Andric return File;
9401d5ae102SDimitry Andric }
9411d5ae102SDimitry Andric
9421d5ae102SDimitry Andric unsigned TBDVersion;
9431d5ae102SDimitry Andric std::vector<UUIDv4> UUIDs;
9441d5ae102SDimitry Andric TargetList Targets;
9451d5ae102SDimitry Andric StringRef InstallName;
9461d5ae102SDimitry Andric PackedVersion CurrentVersion;
9471d5ae102SDimitry Andric PackedVersion CompatibilityVersion;
9481d5ae102SDimitry Andric SwiftVersion SwiftABIVersion{0};
9491d5ae102SDimitry Andric std::vector<MetadataSection> AllowableClients;
9501d5ae102SDimitry Andric std::vector<MetadataSection> ReexportedLibraries;
9511d5ae102SDimitry Andric TBDFlags Flags{TBDFlags::None};
9521d5ae102SDimitry Andric std::vector<UmbrellaSection> ParentUmbrellas;
9531d5ae102SDimitry Andric SectionList Exports;
9541d5ae102SDimitry Andric SectionList Reexports;
9551d5ae102SDimitry Andric SectionList Undefineds;
9561d5ae102SDimitry Andric
9571d5ae102SDimitry Andric private:
assignTargetsToLibraryllvm::yaml::MappingTraits::NormalizedTBD_V49581d5ae102SDimitry Andric void assignTargetsToLibrary(const std::vector<InterfaceFileRef> &Libraries,
9591d5ae102SDimitry Andric std::vector<MetadataSection> &Section) {
9601d5ae102SDimitry Andric std::set<TargetList> targetSet;
9611d5ae102SDimitry Andric std::map<const InterfaceFileRef *, TargetList> valueToTargetList;
9621d5ae102SDimitry Andric for (const auto &library : Libraries) {
9631d5ae102SDimitry Andric TargetList targets(library.targets());
9641d5ae102SDimitry Andric valueToTargetList[&library] = targets;
9651d5ae102SDimitry Andric targetSet.emplace(std::move(targets));
9661d5ae102SDimitry Andric }
9671d5ae102SDimitry Andric
9681d5ae102SDimitry Andric for (const auto &targets : targetSet) {
9691d5ae102SDimitry Andric MetadataSection CurrentSection;
9701d5ae102SDimitry Andric CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
9711d5ae102SDimitry Andric targets.begin(), targets.end());
9721d5ae102SDimitry Andric
9731d5ae102SDimitry Andric for (const auto &it : valueToTargetList) {
9741d5ae102SDimitry Andric if (it.second != targets)
9751d5ae102SDimitry Andric continue;
9761d5ae102SDimitry Andric
9771d5ae102SDimitry Andric CurrentSection.Values.emplace_back(it.first->getInstallName());
9781d5ae102SDimitry Andric }
9791d5ae102SDimitry Andric llvm::sort(CurrentSection.Values);
9801d5ae102SDimitry Andric Section.emplace_back(std::move(CurrentSection));
9811d5ae102SDimitry Andric }
9821d5ae102SDimitry Andric }
9831d5ae102SDimitry Andric };
9841d5ae102SDimitry Andric
mapKeysToValuesllvm::yaml::MappingTraits9851d5ae102SDimitry Andric static void mapKeysToValues(FileType FileKind, IO &IO,
9861d5ae102SDimitry Andric const InterfaceFile *&File) {
9871d5ae102SDimitry Andric MappingNormalization<NormalizedTBD, const InterfaceFile *> Keys(IO, File);
9887fa27ce4SDimitry Andric std::vector<UUID> EmptyUUID;
989e6d15924SDimitry Andric IO.mapRequired("archs", Keys->Architectures);
9901d5ae102SDimitry Andric if (FileKind != FileType::TBD_V1)
9917fa27ce4SDimitry Andric IO.mapOptional("uuids", EmptyUUID);
9921d5ae102SDimitry Andric IO.mapRequired("platform", Keys->Platforms);
9931d5ae102SDimitry Andric if (FileKind != FileType::TBD_V1)
994e6d15924SDimitry Andric IO.mapOptional("flags", Keys->Flags, TBDFlags::None);
995e6d15924SDimitry Andric IO.mapRequired("install-name", Keys->InstallName);
996e6d15924SDimitry Andric IO.mapOptional("current-version", Keys->CurrentVersion,
997e6d15924SDimitry Andric PackedVersion(1, 0, 0));
998e6d15924SDimitry Andric IO.mapOptional("compatibility-version", Keys->CompatibilityVersion,
999e6d15924SDimitry Andric PackedVersion(1, 0, 0));
10001d5ae102SDimitry Andric if (FileKind != FileType::TBD_V3)
1001e6d15924SDimitry Andric IO.mapOptional("swift-version", Keys->SwiftABIVersion, SwiftVersion(0));
1002e6d15924SDimitry Andric else
1003e6d15924SDimitry Andric IO.mapOptional("swift-abi-version", Keys->SwiftABIVersion,
1004e6d15924SDimitry Andric SwiftVersion(0));
1005e6d15924SDimitry Andric IO.mapOptional("objc-constraint", Keys->ObjCConstraint,
10061d5ae102SDimitry Andric (FileKind == FileType::TBD_V1)
1007e6d15924SDimitry Andric ? ObjCConstraintType::None
1008e6d15924SDimitry Andric : ObjCConstraintType::Retain_Release);
10091d5ae102SDimitry Andric if (FileKind != FileType::TBD_V1)
1010e6d15924SDimitry Andric IO.mapOptional("parent-umbrella", Keys->ParentUmbrella, StringRef());
1011e6d15924SDimitry Andric IO.mapOptional("exports", Keys->Exports);
10121d5ae102SDimitry Andric if (FileKind != FileType::TBD_V1)
10131d5ae102SDimitry Andric IO.mapOptional("undefineds", Keys->Undefineds);
10141d5ae102SDimitry Andric }
10151d5ae102SDimitry Andric
mapKeysToValuesV4llvm::yaml::MappingTraits10161d5ae102SDimitry Andric static void mapKeysToValuesV4(IO &IO, const InterfaceFile *&File) {
10171d5ae102SDimitry Andric MappingNormalization<NormalizedTBD_V4, const InterfaceFile *> Keys(IO,
10181d5ae102SDimitry Andric File);
10197fa27ce4SDimitry Andric std::vector<UUIDv4> EmptyUUID;
10201d5ae102SDimitry Andric IO.mapTag("!tapi-tbd", true);
10211d5ae102SDimitry Andric IO.mapRequired("tbd-version", Keys->TBDVersion);
10221d5ae102SDimitry Andric IO.mapRequired("targets", Keys->Targets);
10237fa27ce4SDimitry Andric IO.mapOptional("uuids", EmptyUUID);
10241d5ae102SDimitry Andric IO.mapOptional("flags", Keys->Flags, TBDFlags::None);
10251d5ae102SDimitry Andric IO.mapRequired("install-name", Keys->InstallName);
10261d5ae102SDimitry Andric IO.mapOptional("current-version", Keys->CurrentVersion,
10271d5ae102SDimitry Andric PackedVersion(1, 0, 0));
10281d5ae102SDimitry Andric IO.mapOptional("compatibility-version", Keys->CompatibilityVersion,
10291d5ae102SDimitry Andric PackedVersion(1, 0, 0));
10301d5ae102SDimitry Andric IO.mapOptional("swift-abi-version", Keys->SwiftABIVersion, SwiftVersion(0));
10311d5ae102SDimitry Andric IO.mapOptional("parent-umbrella", Keys->ParentUmbrellas);
10321d5ae102SDimitry Andric auto OptionKind = MetadataSection::Option::Clients;
10331d5ae102SDimitry Andric IO.mapOptionalWithContext("allowable-clients", Keys->AllowableClients,
10341d5ae102SDimitry Andric OptionKind);
10351d5ae102SDimitry Andric OptionKind = MetadataSection::Option::Libraries;
10361d5ae102SDimitry Andric IO.mapOptionalWithContext("reexported-libraries", Keys->ReexportedLibraries,
10371d5ae102SDimitry Andric OptionKind);
10381d5ae102SDimitry Andric IO.mapOptional("exports", Keys->Exports);
10391d5ae102SDimitry Andric IO.mapOptional("reexports", Keys->Reexports);
1040e6d15924SDimitry Andric IO.mapOptional("undefineds", Keys->Undefineds);
1041e6d15924SDimitry Andric }
1042e6d15924SDimitry Andric };
1043e6d15924SDimitry Andric
1044e6d15924SDimitry Andric template <>
1045e6d15924SDimitry Andric struct DocumentListTraits<std::vector<const MachO::InterfaceFile *>> {
sizellvm::yaml::DocumentListTraits1046e6d15924SDimitry Andric static size_t size(IO &IO, std::vector<const MachO::InterfaceFile *> &Seq) {
1047e6d15924SDimitry Andric return Seq.size();
1048e6d15924SDimitry Andric }
1049e6d15924SDimitry Andric static const InterfaceFile *&
elementllvm::yaml::DocumentListTraits1050e6d15924SDimitry Andric element(IO &IO, std::vector<const InterfaceFile *> &Seq, size_t Index) {
1051e6d15924SDimitry Andric if (Index >= Seq.size())
1052e6d15924SDimitry Andric Seq.resize(Index + 1);
1053e6d15924SDimitry Andric return Seq[Index];
1054e6d15924SDimitry Andric }
1055e6d15924SDimitry Andric };
1056e6d15924SDimitry Andric
1057e6d15924SDimitry Andric } // end namespace yaml.
1058cfca06d7SDimitry Andric } // namespace llvm
1059e6d15924SDimitry Andric
DiagHandler(const SMDiagnostic & Diag,void * Context)1060e6d15924SDimitry Andric static void DiagHandler(const SMDiagnostic &Diag, void *Context) {
1061e6d15924SDimitry Andric auto *File = static_cast<TextAPIContext *>(Context);
1062e6d15924SDimitry Andric SmallString<1024> Message;
1063e6d15924SDimitry Andric raw_svector_ostream S(Message);
1064e6d15924SDimitry Andric
1065e6d15924SDimitry Andric SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), File->Path,
1066e6d15924SDimitry Andric Diag.getLineNo(), Diag.getColumnNo(), Diag.getKind(),
1067e6d15924SDimitry Andric Diag.getMessage(), Diag.getLineContents(),
1068e6d15924SDimitry Andric Diag.getRanges(), Diag.getFixIts());
1069e6d15924SDimitry Andric
1070e6d15924SDimitry Andric NewDiag.print(nullptr, S);
1071e6d15924SDimitry Andric File->ErrorMessage = ("malformed file\n" + Message).str();
1072e6d15924SDimitry Andric }
1073e6d15924SDimitry Andric
canRead(MemoryBufferRef InputBuffer)1074b1c73532SDimitry Andric Expected<FileType> TextAPIReader::canRead(MemoryBufferRef InputBuffer) {
10757fa27ce4SDimitry Andric auto TAPIFile = InputBuffer.getBuffer().trim();
1076312c0ed1SDimitry Andric if (TAPIFile.starts_with("{") && TAPIFile.ends_with("}"))
10777fa27ce4SDimitry Andric return FileType::TBD_V5;
10787fa27ce4SDimitry Andric
1079312c0ed1SDimitry Andric if (!TAPIFile.ends_with("..."))
10807fa27ce4SDimitry Andric return createStringError(std::errc::not_supported, "unsupported file type");
10817fa27ce4SDimitry Andric
1082ac9a064cSDimitry Andric if (TAPIFile.starts_with("--- !tapi-tbd"))
10837fa27ce4SDimitry Andric return FileType::TBD_V4;
10847fa27ce4SDimitry Andric
1085ac9a064cSDimitry Andric if (TAPIFile.starts_with("--- !tapi-tbd-v3"))
10867fa27ce4SDimitry Andric return FileType::TBD_V3;
10877fa27ce4SDimitry Andric
1088ac9a064cSDimitry Andric if (TAPIFile.starts_with("--- !tapi-tbd-v2"))
10897fa27ce4SDimitry Andric return FileType::TBD_V2;
10907fa27ce4SDimitry Andric
1091ac9a064cSDimitry Andric if (TAPIFile.starts_with("--- !tapi-tbd-v1") ||
1092312c0ed1SDimitry Andric TAPIFile.starts_with("---\narchs:"))
10937fa27ce4SDimitry Andric return FileType::TBD_V1;
10947fa27ce4SDimitry Andric
10957fa27ce4SDimitry Andric return createStringError(std::errc::not_supported, "unsupported file type");
10967fa27ce4SDimitry Andric }
10977fa27ce4SDimitry Andric
1098e6d15924SDimitry Andric Expected<std::unique_ptr<InterfaceFile>>
get(MemoryBufferRef InputBuffer)10991d5ae102SDimitry Andric TextAPIReader::get(MemoryBufferRef InputBuffer) {
1100e6d15924SDimitry Andric TextAPIContext Ctx;
1101cfca06d7SDimitry Andric Ctx.Path = std::string(InputBuffer.getBufferIdentifier());
1102b1c73532SDimitry Andric if (auto FTOrErr = canRead(InputBuffer))
11037fa27ce4SDimitry Andric Ctx.FileKind = *FTOrErr;
11047fa27ce4SDimitry Andric else
11057fa27ce4SDimitry Andric return FTOrErr.takeError();
11067fa27ce4SDimitry Andric
11077fa27ce4SDimitry Andric // Handle JSON Format.
11087fa27ce4SDimitry Andric if (Ctx.FileKind >= FileType::TBD_V5) {
11097fa27ce4SDimitry Andric auto FileOrErr = getInterfaceFileFromJSON(InputBuffer.getBuffer());
11107fa27ce4SDimitry Andric if (!FileOrErr)
11117fa27ce4SDimitry Andric return FileOrErr.takeError();
1112b1c73532SDimitry Andric
1113b1c73532SDimitry Andric (*FileOrErr)->setPath(Ctx.Path);
11147fa27ce4SDimitry Andric return std::move(*FileOrErr);
11157fa27ce4SDimitry Andric }
11161d5ae102SDimitry Andric yaml::Input YAMLIn(InputBuffer.getBuffer(), &Ctx, DiagHandler, &Ctx);
1117e6d15924SDimitry Andric
1118e6d15924SDimitry Andric // Fill vector with interface file objects created by parsing the YAML file.
1119e6d15924SDimitry Andric std::vector<const InterfaceFile *> Files;
1120e6d15924SDimitry Andric YAMLIn >> Files;
1121e6d15924SDimitry Andric
11221d5ae102SDimitry Andric // YAMLIn dynamically allocates for Interface file and in case of error,
11231d5ae102SDimitry Andric // memory leak will occur unless wrapped around unique_ptr
1124e6d15924SDimitry Andric auto File = std::unique_ptr<InterfaceFile>(
1125e6d15924SDimitry Andric const_cast<InterfaceFile *>(Files.front()));
1126e6d15924SDimitry Andric
1127c0981da4SDimitry Andric for (const InterfaceFile *FI : llvm::drop_begin(Files))
1128cfca06d7SDimitry Andric File->addDocument(
1129c0981da4SDimitry Andric std::shared_ptr<InterfaceFile>(const_cast<InterfaceFile *>(FI)));
1130cfca06d7SDimitry Andric
1131e6d15924SDimitry Andric if (YAMLIn.error())
1132e6d15924SDimitry Andric return make_error<StringError>(Ctx.ErrorMessage, YAMLIn.error());
1133e6d15924SDimitry Andric
1134e6d15924SDimitry Andric return std::move(File);
1135e6d15924SDimitry Andric }
1136e6d15924SDimitry Andric
writeToStream(raw_ostream & OS,const InterfaceFile & File,const FileType FileKind,bool Compact)11377fa27ce4SDimitry Andric Error TextAPIWriter::writeToStream(raw_ostream &OS, const InterfaceFile &File,
1138b1c73532SDimitry Andric const FileType FileKind, bool Compact) {
1139e6d15924SDimitry Andric TextAPIContext Ctx;
1140cfca06d7SDimitry Andric Ctx.Path = std::string(File.getPath());
1141b1c73532SDimitry Andric
1142b1c73532SDimitry Andric // Prefer parameter for format if passed, otherwise fallback to the File
1143b1c73532SDimitry Andric // FileType.
1144b1c73532SDimitry Andric Ctx.FileKind =
1145b1c73532SDimitry Andric (FileKind == FileType::Invalid) ? File.getFileType() : FileKind;
11467fa27ce4SDimitry Andric
11477fa27ce4SDimitry Andric // Write out in JSON format.
11487fa27ce4SDimitry Andric if (Ctx.FileKind >= FileType::TBD_V5) {
1149b1c73532SDimitry Andric return serializeInterfaceFileToJSON(OS, File, Ctx.FileKind, Compact);
11507fa27ce4SDimitry Andric }
11517fa27ce4SDimitry Andric
1152e6d15924SDimitry Andric llvm::yaml::Output YAMLOut(OS, &Ctx, /*WrapColumn=*/80);
1153e6d15924SDimitry Andric
1154e6d15924SDimitry Andric std::vector<const InterfaceFile *> Files;
1155e6d15924SDimitry Andric Files.emplace_back(&File);
1156e6d15924SDimitry Andric
1157b1c73532SDimitry Andric for (const auto &Document : File.documents())
1158cfca06d7SDimitry Andric Files.emplace_back(Document.get());
1159cfca06d7SDimitry Andric
1160e6d15924SDimitry Andric // Stream out yaml.
1161e6d15924SDimitry Andric YAMLOut << Files;
1162e6d15924SDimitry Andric
1163e6d15924SDimitry Andric return Error::success();
1164e6d15924SDimitry Andric }
1165