xref: /src/contrib/llvm-project/llvm/lib/TextAPI/TextStub.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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