xref: /freebsd-src/contrib/llvm-project/llvm/lib/TextAPI/TextStub.cpp (revision 04eeddc0aa8e0a417a16eaf9d7d095207f4a8623)
1fe6060f1SDimitry Andric //===- TextStub.cpp -------------------------------------------------------===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric //
9fe6060f1SDimitry Andric // Implements the text stub file reader/writer.
10fe6060f1SDimitry Andric //
11fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
12fe6060f1SDimitry Andric 
13fe6060f1SDimitry Andric #include "TextAPIContext.h"
14fe6060f1SDimitry Andric #include "TextStubCommon.h"
15fe6060f1SDimitry Andric #include "llvm/ADT/BitmaskEnum.h"
16fe6060f1SDimitry Andric #include "llvm/ADT/SmallString.h"
17fe6060f1SDimitry Andric #include "llvm/ADT/StringRef.h"
18fe6060f1SDimitry Andric #include "llvm/Support/Allocator.h"
19fe6060f1SDimitry Andric #include "llvm/Support/SourceMgr.h"
20fe6060f1SDimitry Andric #include "llvm/Support/YAMLTraits.h"
21fe6060f1SDimitry Andric #include "llvm/Support/raw_ostream.h"
22fe6060f1SDimitry Andric #include "llvm/TextAPI/Architecture.h"
23fe6060f1SDimitry Andric #include "llvm/TextAPI/ArchitectureSet.h"
24fe6060f1SDimitry Andric #include "llvm/TextAPI/InterfaceFile.h"
25fe6060f1SDimitry Andric #include "llvm/TextAPI/PackedVersion.h"
26fe6060f1SDimitry Andric #include "llvm/TextAPI/TextAPIReader.h"
27fe6060f1SDimitry Andric #include "llvm/TextAPI/TextAPIWriter.h"
28fe6060f1SDimitry Andric #include <algorithm>
29fe6060f1SDimitry Andric #include <set>
30fe6060f1SDimitry Andric 
31fe6060f1SDimitry Andric // clang-format off
32fe6060f1SDimitry Andric /*
33fe6060f1SDimitry Andric 
34fe6060f1SDimitry Andric  YAML Format specification.
35fe6060f1SDimitry Andric 
36fe6060f1SDimitry Andric  The TBD v1 format only support two level address libraries and is per
37fe6060f1SDimitry Andric  definition application extension safe.
38fe6060f1SDimitry Andric 
39fe6060f1SDimitry Andric ---                              # the tag !tapi-tbd-v1 is optional and
40fe6060f1SDimitry Andric                                  # shouldn't be emitted to support older linker.
41fe6060f1SDimitry Andric archs: [ armv7, armv7s, arm64 ]  # the list of architecture slices that are
42fe6060f1SDimitry Andric                                  # supported by this file.
43fe6060f1SDimitry Andric platform: ios                    # Specifies the platform (macosx, ios, etc)
44fe6060f1SDimitry Andric install-name: /u/l/libfoo.dylib  #
45fe6060f1SDimitry Andric current-version: 1.2.3           # Optional: defaults to 1.0
46fe6060f1SDimitry Andric compatibility-version: 1.0       # Optional: defaults to 1.0
47fe6060f1SDimitry Andric swift-version: 0                 # Optional: defaults to 0
48fe6060f1SDimitry Andric objc-constraint: none            # Optional: defaults to none
49fe6060f1SDimitry Andric exports:                         # List of export sections
50fe6060f1SDimitry Andric ...
51fe6060f1SDimitry Andric 
52fe6060f1SDimitry Andric Each export section is defined as following:
53fe6060f1SDimitry Andric 
54fe6060f1SDimitry Andric  - archs: [ arm64 ]                   # the list of architecture slices
55fe6060f1SDimitry Andric    allowed-clients: [ client ]        # Optional: List of clients
56fe6060f1SDimitry Andric    re-exports: [ ]                    # Optional: List of re-exports
57fe6060f1SDimitry Andric    symbols: [ _sym ]                  # Optional: List of symbols
58fe6060f1SDimitry Andric    objc-classes: []                   # Optional: List of Objective-C classes
59fe6060f1SDimitry Andric    objc-ivars: []                     # Optional: List of Objective C Instance
60fe6060f1SDimitry Andric                                       #           Variables
61fe6060f1SDimitry Andric    weak-def-symbols: []               # Optional: List of weak defined symbols
62fe6060f1SDimitry Andric    thread-local-symbols: []           # Optional: List of thread local symbols
63fe6060f1SDimitry Andric */
64fe6060f1SDimitry Andric 
65fe6060f1SDimitry Andric /*
66fe6060f1SDimitry Andric 
67fe6060f1SDimitry Andric  YAML Format specification.
68fe6060f1SDimitry Andric 
69fe6060f1SDimitry Andric --- !tapi-tbd-v2
70fe6060f1SDimitry Andric archs: [ armv7, armv7s, arm64 ]  # the list of architecture slices that are
71fe6060f1SDimitry Andric                                  # supported by this file.
72fe6060f1SDimitry Andric uuids: [ armv7:... ]             # Optional: List of architecture and UUID pairs.
73fe6060f1SDimitry Andric platform: ios                    # Specifies the platform (macosx, ios, etc)
74fe6060f1SDimitry Andric flags: []                        # Optional:
75fe6060f1SDimitry Andric install-name: /u/l/libfoo.dylib  #
76fe6060f1SDimitry Andric current-version: 1.2.3           # Optional: defaults to 1.0
77fe6060f1SDimitry Andric compatibility-version: 1.0       # Optional: defaults to 1.0
78fe6060f1SDimitry Andric swift-version: 0                 # Optional: defaults to 0
79fe6060f1SDimitry Andric objc-constraint: retain_release  # Optional: defaults to retain_release
80fe6060f1SDimitry Andric parent-umbrella:                 # Optional:
81fe6060f1SDimitry Andric exports:                         # List of export sections
82fe6060f1SDimitry Andric ...
83fe6060f1SDimitry Andric undefineds:                      # List of undefineds sections
84fe6060f1SDimitry Andric ...
85fe6060f1SDimitry Andric 
86fe6060f1SDimitry Andric Each export section is defined as following:
87fe6060f1SDimitry Andric 
88fe6060f1SDimitry Andric - archs: [ arm64 ]                   # the list of architecture slices
89fe6060f1SDimitry Andric   allowed-clients: [ client ]        # Optional: List of clients
90fe6060f1SDimitry Andric   re-exports: [ ]                    # Optional: List of re-exports
91fe6060f1SDimitry Andric   symbols: [ _sym ]                  # Optional: List of symbols
92fe6060f1SDimitry Andric   objc-classes: []                   # Optional: List of Objective-C classes
93fe6060f1SDimitry Andric   objc-ivars: []                     # Optional: List of Objective C Instance
94fe6060f1SDimitry Andric                                      #           Variables
95fe6060f1SDimitry Andric   weak-def-symbols: []               # Optional: List of weak defined symbols
96fe6060f1SDimitry Andric   thread-local-symbols: []           # Optional: List of thread local symbols
97fe6060f1SDimitry Andric 
98fe6060f1SDimitry Andric Each undefineds section is defined as following:
99fe6060f1SDimitry Andric - archs: [ arm64 ]     # the list of architecture slices
100fe6060f1SDimitry Andric   symbols: [ _sym ]    # Optional: List of symbols
101fe6060f1SDimitry Andric   objc-classes: []     # Optional: List of Objective-C classes
102fe6060f1SDimitry Andric   objc-ivars: []       # Optional: List of Objective C Instance Variables
103fe6060f1SDimitry Andric   weak-ref-symbols: [] # Optional: List of weak defined symbols
104fe6060f1SDimitry Andric */
105fe6060f1SDimitry Andric 
106fe6060f1SDimitry Andric /*
107fe6060f1SDimitry Andric 
108fe6060f1SDimitry Andric  YAML Format specification.
109fe6060f1SDimitry Andric 
110fe6060f1SDimitry Andric --- !tapi-tbd-v3
111fe6060f1SDimitry Andric archs: [ armv7, armv7s, arm64 ]  # the list of architecture slices that are
112fe6060f1SDimitry Andric                                  # supported by this file.
113fe6060f1SDimitry Andric uuids: [ armv7:... ]             # Optional: List of architecture and UUID pairs.
114fe6060f1SDimitry Andric platform: ios                    # Specifies the platform (macosx, ios, etc)
115fe6060f1SDimitry Andric flags: []                        # Optional:
116fe6060f1SDimitry Andric install-name: /u/l/libfoo.dylib  #
117fe6060f1SDimitry Andric current-version: 1.2.3           # Optional: defaults to 1.0
118fe6060f1SDimitry Andric compatibility-version: 1.0       # Optional: defaults to 1.0
119fe6060f1SDimitry Andric swift-abi-version: 0             # Optional: defaults to 0
120fe6060f1SDimitry Andric objc-constraint: retain_release  # Optional: defaults to retain_release
121fe6060f1SDimitry Andric parent-umbrella:                 # Optional:
122fe6060f1SDimitry Andric exports:                         # List of export sections
123fe6060f1SDimitry Andric ...
124fe6060f1SDimitry Andric undefineds:                      # List of undefineds sections
125fe6060f1SDimitry Andric ...
126fe6060f1SDimitry Andric 
127fe6060f1SDimitry Andric Each export section is defined as following:
128fe6060f1SDimitry Andric 
129fe6060f1SDimitry Andric - archs: [ arm64 ]                   # the list of architecture slices
130fe6060f1SDimitry Andric   allowed-clients: [ client ]        # Optional: List of clients
131fe6060f1SDimitry Andric   re-exports: [ ]                    # Optional: List of re-exports
132fe6060f1SDimitry Andric   symbols: [ _sym ]                  # Optional: List of symbols
133fe6060f1SDimitry Andric   objc-classes: []                   # Optional: List of Objective-C classes
134fe6060f1SDimitry Andric   objc-eh-types: []                  # Optional: List of Objective-C classes
135fe6060f1SDimitry Andric                                      #           with EH
136fe6060f1SDimitry Andric   objc-ivars: []                     # Optional: List of Objective C Instance
137fe6060f1SDimitry Andric                                      #           Variables
138fe6060f1SDimitry Andric   weak-def-symbols: []               # Optional: List of weak defined symbols
139fe6060f1SDimitry Andric   thread-local-symbols: []           # Optional: List of thread local symbols
140fe6060f1SDimitry Andric 
141fe6060f1SDimitry Andric Each undefineds section is defined as following:
142fe6060f1SDimitry Andric - archs: [ arm64 ]     # the list of architecture slices
143fe6060f1SDimitry Andric   symbols: [ _sym ]    # Optional: List of symbols
144fe6060f1SDimitry Andric   objc-classes: []     # Optional: List of Objective-C classes
145fe6060f1SDimitry Andric   objc-eh-types: []                  # Optional: List of Objective-C classes
146fe6060f1SDimitry Andric                                      #           with EH
147fe6060f1SDimitry Andric   objc-ivars: []       # Optional: List of Objective C Instance Variables
148fe6060f1SDimitry Andric   weak-ref-symbols: [] # Optional: List of weak defined symbols
149fe6060f1SDimitry Andric */
150fe6060f1SDimitry Andric 
151fe6060f1SDimitry Andric /*
152fe6060f1SDimitry Andric 
153fe6060f1SDimitry Andric  YAML Format specification.
154fe6060f1SDimitry Andric 
155fe6060f1SDimitry Andric --- !tapi-tbd
156fe6060f1SDimitry Andric tbd-version: 4                              # The tbd version for format
157fe6060f1SDimitry Andric targets: [ armv7-ios, x86_64-maccatalyst ]  # The list of applicable tapi supported target triples
158fe6060f1SDimitry Andric uuids:                                      # Optional: List of target and UUID pairs.
159fe6060f1SDimitry Andric   - target: armv7-ios
160fe6060f1SDimitry Andric     value: ...
161fe6060f1SDimitry Andric   - target: x86_64-maccatalyst
162fe6060f1SDimitry Andric     value: ...
163fe6060f1SDimitry Andric flags: []                        # Optional:
164fe6060f1SDimitry Andric install-name: /u/l/libfoo.dylib  #
165fe6060f1SDimitry Andric current-version: 1.2.3           # Optional: defaults to 1.0
166fe6060f1SDimitry Andric compatibility-version: 1.0       # Optional: defaults to 1.0
167fe6060f1SDimitry Andric swift-abi-version: 0             # Optional: defaults to 0
168fe6060f1SDimitry Andric parent-umbrella:                 # Optional:
169fe6060f1SDimitry Andric allowable-clients:
170fe6060f1SDimitry Andric   - targets: [ armv7-ios ]       # Optional:
171fe6060f1SDimitry Andric     clients: [ clientA ]
172fe6060f1SDimitry Andric exports:                         # List of export sections
173fe6060f1SDimitry Andric ...
174fe6060f1SDimitry Andric re-exports:                      # List of reexport sections
175fe6060f1SDimitry Andric ...
176fe6060f1SDimitry Andric undefineds:                      # List of undefineds sections
177fe6060f1SDimitry Andric ...
178fe6060f1SDimitry Andric 
179fe6060f1SDimitry Andric Each export and reexport  section is defined as following:
180fe6060f1SDimitry Andric 
181fe6060f1SDimitry Andric - targets: [ arm64-macos ]                        # The list of target triples associated with symbols
182fe6060f1SDimitry Andric   symbols: [ _symA ]                              # Optional: List of symbols
183fe6060f1SDimitry Andric   objc-classes: []                                # Optional: List of Objective-C classes
184fe6060f1SDimitry Andric   objc-eh-types: []                               # Optional: List of Objective-C classes
185fe6060f1SDimitry Andric                                                   #           with EH
186fe6060f1SDimitry Andric   objc-ivars: []                                  # Optional: List of Objective C Instance
187fe6060f1SDimitry Andric                                                   #           Variables
188fe6060f1SDimitry Andric   weak-symbols: []                                # Optional: List of weak defined symbols
189fe6060f1SDimitry Andric   thread-local-symbols: []                        # Optional: List of thread local symbols
190fe6060f1SDimitry Andric - targets: [ arm64-macos, x86_64-maccatalyst ]    # Optional: Targets for applicable additional symbols
191fe6060f1SDimitry Andric   symbols: [ _symB ]                              # Optional: List of symbols
192fe6060f1SDimitry Andric 
193fe6060f1SDimitry Andric Each undefineds section is defined as following:
194fe6060f1SDimitry Andric - targets: [ arm64-macos ]    # The list of target triples associated with symbols
195fe6060f1SDimitry Andric   symbols: [ _symC ]          # Optional: List of symbols
196fe6060f1SDimitry Andric   objc-classes: []            # Optional: List of Objective-C classes
197fe6060f1SDimitry Andric   objc-eh-types: []           # Optional: List of Objective-C classes
198fe6060f1SDimitry Andric                               #           with EH
199fe6060f1SDimitry Andric   objc-ivars: []              # Optional: List of Objective C Instance Variables
200fe6060f1SDimitry Andric   weak-symbols: []            # Optional: List of weak defined symbols
201fe6060f1SDimitry Andric */
202fe6060f1SDimitry Andric // clang-format on
203fe6060f1SDimitry Andric 
204fe6060f1SDimitry Andric using namespace llvm;
205fe6060f1SDimitry Andric using namespace llvm::yaml;
206fe6060f1SDimitry Andric using namespace llvm::MachO;
207fe6060f1SDimitry Andric 
208fe6060f1SDimitry Andric namespace {
209fe6060f1SDimitry Andric struct ExportSection {
210fe6060f1SDimitry Andric   std::vector<Architecture> Architectures;
211fe6060f1SDimitry Andric   std::vector<FlowStringRef> AllowableClients;
212fe6060f1SDimitry Andric   std::vector<FlowStringRef> ReexportedLibraries;
213fe6060f1SDimitry Andric   std::vector<FlowStringRef> Symbols;
214fe6060f1SDimitry Andric   std::vector<FlowStringRef> Classes;
215fe6060f1SDimitry Andric   std::vector<FlowStringRef> ClassEHs;
216fe6060f1SDimitry Andric   std::vector<FlowStringRef> IVars;
217fe6060f1SDimitry Andric   std::vector<FlowStringRef> WeakDefSymbols;
218fe6060f1SDimitry Andric   std::vector<FlowStringRef> TLVSymbols;
219fe6060f1SDimitry Andric };
220fe6060f1SDimitry Andric 
221fe6060f1SDimitry Andric struct UndefinedSection {
222fe6060f1SDimitry Andric   std::vector<Architecture> Architectures;
223fe6060f1SDimitry Andric   std::vector<FlowStringRef> Symbols;
224fe6060f1SDimitry Andric   std::vector<FlowStringRef> Classes;
225fe6060f1SDimitry Andric   std::vector<FlowStringRef> ClassEHs;
226fe6060f1SDimitry Andric   std::vector<FlowStringRef> IVars;
227fe6060f1SDimitry Andric   std::vector<FlowStringRef> WeakRefSymbols;
228fe6060f1SDimitry Andric };
229fe6060f1SDimitry Andric 
230fe6060f1SDimitry Andric // Sections for direct target mapping in TBDv4
231fe6060f1SDimitry Andric struct SymbolSection {
232fe6060f1SDimitry Andric   TargetList Targets;
233fe6060f1SDimitry Andric   std::vector<FlowStringRef> Symbols;
234fe6060f1SDimitry Andric   std::vector<FlowStringRef> Classes;
235fe6060f1SDimitry Andric   std::vector<FlowStringRef> ClassEHs;
236fe6060f1SDimitry Andric   std::vector<FlowStringRef> Ivars;
237fe6060f1SDimitry Andric   std::vector<FlowStringRef> WeakSymbols;
238fe6060f1SDimitry Andric   std::vector<FlowStringRef> TlvSymbols;
239fe6060f1SDimitry Andric };
240fe6060f1SDimitry Andric 
241fe6060f1SDimitry Andric struct MetadataSection {
242fe6060f1SDimitry Andric   enum Option { Clients, Libraries };
243fe6060f1SDimitry Andric   std::vector<Target> Targets;
244fe6060f1SDimitry Andric   std::vector<FlowStringRef> Values;
245fe6060f1SDimitry Andric };
246fe6060f1SDimitry Andric 
247fe6060f1SDimitry Andric struct UmbrellaSection {
248fe6060f1SDimitry Andric   std::vector<Target> Targets;
249fe6060f1SDimitry Andric   std::string Umbrella;
250fe6060f1SDimitry Andric };
251fe6060f1SDimitry Andric 
252fe6060f1SDimitry Andric // UUID's for TBDv4 are mapped to target not arch
253fe6060f1SDimitry Andric struct UUIDv4 {
254fe6060f1SDimitry Andric   Target TargetID;
255fe6060f1SDimitry Andric   std::string Value;
256fe6060f1SDimitry Andric 
257fe6060f1SDimitry Andric   UUIDv4() = default;
258fe6060f1SDimitry Andric   UUIDv4(const Target &TargetID, const std::string &Value)
259fe6060f1SDimitry Andric       : TargetID(TargetID), Value(Value) {}
260fe6060f1SDimitry Andric };
261fe6060f1SDimitry Andric 
262fe6060f1SDimitry Andric // clang-format off
263fe6060f1SDimitry Andric enum TBDFlags : unsigned {
264fe6060f1SDimitry Andric   None                         = 0U,
265fe6060f1SDimitry Andric   FlatNamespace                = 1U << 0,
266fe6060f1SDimitry Andric   NotApplicationExtensionSafe  = 1U << 1,
267fe6060f1SDimitry Andric   InstallAPI                   = 1U << 2,
268fe6060f1SDimitry Andric   LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/InstallAPI),
269fe6060f1SDimitry Andric };
270fe6060f1SDimitry Andric // clang-format on
271fe6060f1SDimitry Andric } // end anonymous namespace.
272fe6060f1SDimitry Andric 
273fe6060f1SDimitry Andric LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(Architecture)
274fe6060f1SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(ExportSection)
275fe6060f1SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(UndefinedSection)
276fe6060f1SDimitry Andric // Specific to TBDv4
277fe6060f1SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(SymbolSection)
278fe6060f1SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(MetadataSection)
279fe6060f1SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(UmbrellaSection)
280fe6060f1SDimitry Andric LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(Target)
281fe6060f1SDimitry Andric LLVM_YAML_IS_SEQUENCE_VECTOR(UUIDv4)
282fe6060f1SDimitry Andric 
283fe6060f1SDimitry Andric namespace llvm {
284fe6060f1SDimitry Andric namespace yaml {
285fe6060f1SDimitry Andric 
286fe6060f1SDimitry Andric template <> struct MappingTraits<ExportSection> {
287fe6060f1SDimitry Andric   static void mapping(IO &IO, ExportSection &Section) {
288fe6060f1SDimitry Andric     const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
289fe6060f1SDimitry Andric     assert((!Ctx || (Ctx && Ctx->FileKind != FileType::Invalid)) &&
290fe6060f1SDimitry Andric            "File type is not set in YAML context");
291fe6060f1SDimitry Andric 
292fe6060f1SDimitry Andric     IO.mapRequired("archs", Section.Architectures);
293fe6060f1SDimitry Andric     if (Ctx->FileKind == FileType::TBD_V1)
294fe6060f1SDimitry Andric       IO.mapOptional("allowed-clients", Section.AllowableClients);
295fe6060f1SDimitry Andric     else
296fe6060f1SDimitry Andric       IO.mapOptional("allowable-clients", Section.AllowableClients);
297fe6060f1SDimitry Andric     IO.mapOptional("re-exports", Section.ReexportedLibraries);
298fe6060f1SDimitry Andric     IO.mapOptional("symbols", Section.Symbols);
299fe6060f1SDimitry Andric     IO.mapOptional("objc-classes", Section.Classes);
300fe6060f1SDimitry Andric     if (Ctx->FileKind == FileType::TBD_V3)
301fe6060f1SDimitry Andric       IO.mapOptional("objc-eh-types", Section.ClassEHs);
302fe6060f1SDimitry Andric     IO.mapOptional("objc-ivars", Section.IVars);
303fe6060f1SDimitry Andric     IO.mapOptional("weak-def-symbols", Section.WeakDefSymbols);
304fe6060f1SDimitry Andric     IO.mapOptional("thread-local-symbols", Section.TLVSymbols);
305fe6060f1SDimitry Andric   }
306fe6060f1SDimitry Andric };
307fe6060f1SDimitry Andric 
308fe6060f1SDimitry Andric template <> struct MappingTraits<UndefinedSection> {
309fe6060f1SDimitry Andric   static void mapping(IO &IO, UndefinedSection &Section) {
310fe6060f1SDimitry Andric     const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
311fe6060f1SDimitry Andric     assert((!Ctx || (Ctx && Ctx->FileKind != FileType::Invalid)) &&
312fe6060f1SDimitry Andric            "File type is not set in YAML context");
313fe6060f1SDimitry Andric 
314fe6060f1SDimitry Andric     IO.mapRequired("archs", Section.Architectures);
315fe6060f1SDimitry Andric     IO.mapOptional("symbols", Section.Symbols);
316fe6060f1SDimitry Andric     IO.mapOptional("objc-classes", Section.Classes);
317fe6060f1SDimitry Andric     if (Ctx->FileKind == FileType::TBD_V3)
318fe6060f1SDimitry Andric       IO.mapOptional("objc-eh-types", Section.ClassEHs);
319fe6060f1SDimitry Andric     IO.mapOptional("objc-ivars", Section.IVars);
320fe6060f1SDimitry Andric     IO.mapOptional("weak-ref-symbols", Section.WeakRefSymbols);
321fe6060f1SDimitry Andric   }
322fe6060f1SDimitry Andric };
323fe6060f1SDimitry Andric 
324fe6060f1SDimitry Andric template <> struct MappingTraits<SymbolSection> {
325fe6060f1SDimitry Andric   static void mapping(IO &IO, SymbolSection &Section) {
326fe6060f1SDimitry Andric     IO.mapRequired("targets", Section.Targets);
327fe6060f1SDimitry Andric     IO.mapOptional("symbols", Section.Symbols);
328fe6060f1SDimitry Andric     IO.mapOptional("objc-classes", Section.Classes);
329fe6060f1SDimitry Andric     IO.mapOptional("objc-eh-types", Section.ClassEHs);
330fe6060f1SDimitry Andric     IO.mapOptional("objc-ivars", Section.Ivars);
331fe6060f1SDimitry Andric     IO.mapOptional("weak-symbols", Section.WeakSymbols);
332fe6060f1SDimitry Andric     IO.mapOptional("thread-local-symbols", Section.TlvSymbols);
333fe6060f1SDimitry Andric   }
334fe6060f1SDimitry Andric };
335fe6060f1SDimitry Andric 
336fe6060f1SDimitry Andric template <> struct MappingTraits<UmbrellaSection> {
337fe6060f1SDimitry Andric   static void mapping(IO &IO, UmbrellaSection &Section) {
338fe6060f1SDimitry Andric     IO.mapRequired("targets", Section.Targets);
339fe6060f1SDimitry Andric     IO.mapRequired("umbrella", Section.Umbrella);
340fe6060f1SDimitry Andric   }
341fe6060f1SDimitry Andric };
342fe6060f1SDimitry Andric 
343fe6060f1SDimitry Andric template <> struct MappingTraits<UUIDv4> {
344fe6060f1SDimitry Andric   static void mapping(IO &IO, UUIDv4 &UUID) {
345fe6060f1SDimitry Andric     IO.mapRequired("target", UUID.TargetID);
346fe6060f1SDimitry Andric     IO.mapRequired("value", UUID.Value);
347fe6060f1SDimitry Andric   }
348fe6060f1SDimitry Andric };
349fe6060f1SDimitry Andric 
350fe6060f1SDimitry Andric template <>
351fe6060f1SDimitry Andric struct MappingContextTraits<MetadataSection, MetadataSection::Option> {
352fe6060f1SDimitry Andric   static void mapping(IO &IO, MetadataSection &Section,
353fe6060f1SDimitry Andric                       MetadataSection::Option &OptionKind) {
354fe6060f1SDimitry Andric     IO.mapRequired("targets", Section.Targets);
355fe6060f1SDimitry Andric     switch (OptionKind) {
356fe6060f1SDimitry Andric     case MetadataSection::Option::Clients:
357fe6060f1SDimitry Andric       IO.mapRequired("clients", Section.Values);
358fe6060f1SDimitry Andric       return;
359fe6060f1SDimitry Andric     case MetadataSection::Option::Libraries:
360fe6060f1SDimitry Andric       IO.mapRequired("libraries", Section.Values);
361fe6060f1SDimitry Andric       return;
362fe6060f1SDimitry Andric     }
363fe6060f1SDimitry Andric     llvm_unreachable("unexpected option for metadata");
364fe6060f1SDimitry Andric   }
365fe6060f1SDimitry Andric };
366fe6060f1SDimitry Andric 
367fe6060f1SDimitry Andric template <> struct ScalarBitSetTraits<TBDFlags> {
368fe6060f1SDimitry Andric   static void bitset(IO &IO, TBDFlags &Flags) {
369fe6060f1SDimitry Andric     IO.bitSetCase(Flags, "flat_namespace", TBDFlags::FlatNamespace);
370fe6060f1SDimitry Andric     IO.bitSetCase(Flags, "not_app_extension_safe",
371fe6060f1SDimitry Andric                   TBDFlags::NotApplicationExtensionSafe);
372fe6060f1SDimitry Andric     IO.bitSetCase(Flags, "installapi", TBDFlags::InstallAPI);
373fe6060f1SDimitry Andric   }
374fe6060f1SDimitry Andric };
375fe6060f1SDimitry Andric 
376fe6060f1SDimitry Andric template <> struct ScalarTraits<Target> {
377fe6060f1SDimitry Andric   static void output(const Target &Value, void *, raw_ostream &OS) {
378fe6060f1SDimitry Andric     OS << Value.Arch << "-";
379fe6060f1SDimitry Andric     switch (Value.Platform) {
380fe6060f1SDimitry Andric     default:
381fe6060f1SDimitry Andric       OS << "unknown";
382fe6060f1SDimitry Andric       break;
383*04eeddc0SDimitry Andric     case PLATFORM_MACOS:
384fe6060f1SDimitry Andric       OS << "macos";
385fe6060f1SDimitry Andric       break;
386*04eeddc0SDimitry Andric     case PLATFORM_IOS:
387fe6060f1SDimitry Andric       OS << "ios";
388fe6060f1SDimitry Andric       break;
389*04eeddc0SDimitry Andric     case PLATFORM_TVOS:
390fe6060f1SDimitry Andric       OS << "tvos";
391fe6060f1SDimitry Andric       break;
392*04eeddc0SDimitry Andric     case PLATFORM_WATCHOS:
393fe6060f1SDimitry Andric       OS << "watchos";
394fe6060f1SDimitry Andric       break;
395*04eeddc0SDimitry Andric     case PLATFORM_BRIDGEOS:
396fe6060f1SDimitry Andric       OS << "bridgeos";
397fe6060f1SDimitry Andric       break;
398*04eeddc0SDimitry Andric     case PLATFORM_MACCATALYST:
399fe6060f1SDimitry Andric       OS << "maccatalyst";
400fe6060f1SDimitry Andric       break;
401*04eeddc0SDimitry Andric     case PLATFORM_IOSSIMULATOR:
402fe6060f1SDimitry Andric       OS << "ios-simulator";
403fe6060f1SDimitry Andric       break;
404*04eeddc0SDimitry Andric     case PLATFORM_TVOSSIMULATOR:
405fe6060f1SDimitry Andric       OS << "tvos-simulator";
406fe6060f1SDimitry Andric       break;
407*04eeddc0SDimitry Andric     case PLATFORM_WATCHOSSIMULATOR:
408fe6060f1SDimitry Andric       OS << "watchos-simulator";
409fe6060f1SDimitry Andric       break;
410*04eeddc0SDimitry Andric     case PLATFORM_DRIVERKIT:
411fe6060f1SDimitry Andric       OS << "driverkit";
412fe6060f1SDimitry Andric       break;
413fe6060f1SDimitry Andric     }
414fe6060f1SDimitry Andric   }
415fe6060f1SDimitry Andric 
416fe6060f1SDimitry Andric   static StringRef input(StringRef Scalar, void *, Target &Value) {
417fe6060f1SDimitry Andric     auto Result = Target::create(Scalar);
418fe6060f1SDimitry Andric     if (!Result) {
419fe6060f1SDimitry Andric       consumeError(Result.takeError());
420fe6060f1SDimitry Andric       return "unparsable target";
421fe6060f1SDimitry Andric     }
422fe6060f1SDimitry Andric 
423fe6060f1SDimitry Andric     Value = *Result;
424fe6060f1SDimitry Andric     if (Value.Arch == AK_unknown)
425fe6060f1SDimitry Andric       return "unknown architecture";
426*04eeddc0SDimitry Andric     if (Value.Platform == PLATFORM_UNKNOWN)
427fe6060f1SDimitry Andric       return "unknown platform";
428fe6060f1SDimitry Andric 
429fe6060f1SDimitry Andric     return {};
430fe6060f1SDimitry Andric   }
431fe6060f1SDimitry Andric 
432fe6060f1SDimitry Andric   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
433fe6060f1SDimitry Andric };
434fe6060f1SDimitry Andric 
435fe6060f1SDimitry Andric template <> struct MappingTraits<const InterfaceFile *> {
436fe6060f1SDimitry Andric   struct NormalizedTBD {
437fe6060f1SDimitry Andric     explicit NormalizedTBD(IO &IO) {}
438fe6060f1SDimitry Andric     NormalizedTBD(IO &IO, const InterfaceFile *&File) {
439fe6060f1SDimitry Andric       Architectures = File->getArchitectures();
440fe6060f1SDimitry Andric       UUIDs = File->uuids();
441fe6060f1SDimitry Andric       Platforms = File->getPlatforms();
442fe6060f1SDimitry Andric       InstallName = File->getInstallName();
443fe6060f1SDimitry Andric       CurrentVersion = PackedVersion(File->getCurrentVersion());
444fe6060f1SDimitry Andric       CompatibilityVersion = PackedVersion(File->getCompatibilityVersion());
445fe6060f1SDimitry Andric       SwiftABIVersion = File->getSwiftABIVersion();
446fe6060f1SDimitry Andric       ObjCConstraint = File->getObjCConstraint();
447fe6060f1SDimitry Andric 
448fe6060f1SDimitry Andric       Flags = TBDFlags::None;
449fe6060f1SDimitry Andric       if (!File->isApplicationExtensionSafe())
450fe6060f1SDimitry Andric         Flags |= TBDFlags::NotApplicationExtensionSafe;
451fe6060f1SDimitry Andric 
452fe6060f1SDimitry Andric       if (!File->isTwoLevelNamespace())
453fe6060f1SDimitry Andric         Flags |= TBDFlags::FlatNamespace;
454fe6060f1SDimitry Andric 
455fe6060f1SDimitry Andric       if (File->isInstallAPI())
456fe6060f1SDimitry Andric         Flags |= TBDFlags::InstallAPI;
457fe6060f1SDimitry Andric 
458fe6060f1SDimitry Andric       if (!File->umbrellas().empty())
459fe6060f1SDimitry Andric         ParentUmbrella = File->umbrellas().begin()->second;
460fe6060f1SDimitry Andric 
461fe6060f1SDimitry Andric       std::set<ArchitectureSet> ArchSet;
462fe6060f1SDimitry Andric       for (const auto &Library : File->allowableClients())
463fe6060f1SDimitry Andric         ArchSet.insert(Library.getArchitectures());
464fe6060f1SDimitry Andric 
465fe6060f1SDimitry Andric       for (const auto &Library : File->reexportedLibraries())
466fe6060f1SDimitry Andric         ArchSet.insert(Library.getArchitectures());
467fe6060f1SDimitry Andric 
468fe6060f1SDimitry Andric       std::map<const Symbol *, ArchitectureSet> SymbolToArchSet;
469fe6060f1SDimitry Andric       for (const auto *Symbol : File->exports()) {
470fe6060f1SDimitry Andric         auto Architectures = Symbol->getArchitectures();
471fe6060f1SDimitry Andric         SymbolToArchSet[Symbol] = Architectures;
472fe6060f1SDimitry Andric         ArchSet.insert(Architectures);
473fe6060f1SDimitry Andric       }
474fe6060f1SDimitry Andric 
475fe6060f1SDimitry Andric       for (auto Architectures : ArchSet) {
476fe6060f1SDimitry Andric         ExportSection Section;
477fe6060f1SDimitry Andric         Section.Architectures = Architectures;
478fe6060f1SDimitry Andric 
479fe6060f1SDimitry Andric         for (const auto &Library : File->allowableClients())
480fe6060f1SDimitry Andric           if (Library.getArchitectures() == Architectures)
481fe6060f1SDimitry Andric             Section.AllowableClients.emplace_back(Library.getInstallName());
482fe6060f1SDimitry Andric 
483fe6060f1SDimitry Andric         for (const auto &Library : File->reexportedLibraries())
484fe6060f1SDimitry Andric           if (Library.getArchitectures() == Architectures)
485fe6060f1SDimitry Andric             Section.ReexportedLibraries.emplace_back(Library.getInstallName());
486fe6060f1SDimitry Andric 
487fe6060f1SDimitry Andric         for (const auto &SymArch : SymbolToArchSet) {
488fe6060f1SDimitry Andric           if (SymArch.second != Architectures)
489fe6060f1SDimitry Andric             continue;
490fe6060f1SDimitry Andric 
491fe6060f1SDimitry Andric           const auto *Symbol = SymArch.first;
492fe6060f1SDimitry Andric           switch (Symbol->getKind()) {
493fe6060f1SDimitry Andric           case SymbolKind::GlobalSymbol:
494fe6060f1SDimitry Andric             if (Symbol->isWeakDefined())
495fe6060f1SDimitry Andric               Section.WeakDefSymbols.emplace_back(Symbol->getName());
496fe6060f1SDimitry Andric             else if (Symbol->isThreadLocalValue())
497fe6060f1SDimitry Andric               Section.TLVSymbols.emplace_back(Symbol->getName());
498fe6060f1SDimitry Andric             else
499fe6060f1SDimitry Andric               Section.Symbols.emplace_back(Symbol->getName());
500fe6060f1SDimitry Andric             break;
501fe6060f1SDimitry Andric           case SymbolKind::ObjectiveCClass:
502fe6060f1SDimitry Andric             if (File->getFileType() != FileType::TBD_V3)
503fe6060f1SDimitry Andric               Section.Classes.emplace_back(
504fe6060f1SDimitry Andric                   copyString("_" + Symbol->getName().str()));
505fe6060f1SDimitry Andric             else
506fe6060f1SDimitry Andric               Section.Classes.emplace_back(Symbol->getName());
507fe6060f1SDimitry Andric             break;
508fe6060f1SDimitry Andric           case SymbolKind::ObjectiveCClassEHType:
509fe6060f1SDimitry Andric             if (File->getFileType() != FileType::TBD_V3)
510fe6060f1SDimitry Andric               Section.Symbols.emplace_back(
511fe6060f1SDimitry Andric                   copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str()));
512fe6060f1SDimitry Andric             else
513fe6060f1SDimitry Andric               Section.ClassEHs.emplace_back(Symbol->getName());
514fe6060f1SDimitry Andric             break;
515fe6060f1SDimitry Andric           case SymbolKind::ObjectiveCInstanceVariable:
516fe6060f1SDimitry Andric             if (File->getFileType() != FileType::TBD_V3)
517fe6060f1SDimitry Andric               Section.IVars.emplace_back(
518fe6060f1SDimitry Andric                   copyString("_" + Symbol->getName().str()));
519fe6060f1SDimitry Andric             else
520fe6060f1SDimitry Andric               Section.IVars.emplace_back(Symbol->getName());
521fe6060f1SDimitry Andric             break;
522fe6060f1SDimitry Andric           }
523fe6060f1SDimitry Andric         }
524fe6060f1SDimitry Andric         llvm::sort(Section.Symbols);
525fe6060f1SDimitry Andric         llvm::sort(Section.Classes);
526fe6060f1SDimitry Andric         llvm::sort(Section.ClassEHs);
527fe6060f1SDimitry Andric         llvm::sort(Section.IVars);
528fe6060f1SDimitry Andric         llvm::sort(Section.WeakDefSymbols);
529fe6060f1SDimitry Andric         llvm::sort(Section.TLVSymbols);
530fe6060f1SDimitry Andric         Exports.emplace_back(std::move(Section));
531fe6060f1SDimitry Andric       }
532fe6060f1SDimitry Andric 
533fe6060f1SDimitry Andric       ArchSet.clear();
534fe6060f1SDimitry Andric       SymbolToArchSet.clear();
535fe6060f1SDimitry Andric 
536fe6060f1SDimitry Andric       for (const auto *Symbol : File->undefineds()) {
537fe6060f1SDimitry Andric         auto Architectures = Symbol->getArchitectures();
538fe6060f1SDimitry Andric         SymbolToArchSet[Symbol] = Architectures;
539fe6060f1SDimitry Andric         ArchSet.insert(Architectures);
540fe6060f1SDimitry Andric       }
541fe6060f1SDimitry Andric 
542fe6060f1SDimitry Andric       for (auto Architectures : ArchSet) {
543fe6060f1SDimitry Andric         UndefinedSection Section;
544fe6060f1SDimitry Andric         Section.Architectures = Architectures;
545fe6060f1SDimitry Andric 
546fe6060f1SDimitry Andric         for (const auto &SymArch : SymbolToArchSet) {
547fe6060f1SDimitry Andric           if (SymArch.second != Architectures)
548fe6060f1SDimitry Andric             continue;
549fe6060f1SDimitry Andric 
550fe6060f1SDimitry Andric           const auto *Symbol = SymArch.first;
551fe6060f1SDimitry Andric           switch (Symbol->getKind()) {
552fe6060f1SDimitry Andric           case SymbolKind::GlobalSymbol:
553fe6060f1SDimitry Andric             if (Symbol->isWeakReferenced())
554fe6060f1SDimitry Andric               Section.WeakRefSymbols.emplace_back(Symbol->getName());
555fe6060f1SDimitry Andric             else
556fe6060f1SDimitry Andric               Section.Symbols.emplace_back(Symbol->getName());
557fe6060f1SDimitry Andric             break;
558fe6060f1SDimitry Andric           case SymbolKind::ObjectiveCClass:
559fe6060f1SDimitry Andric             if (File->getFileType() != FileType::TBD_V3)
560fe6060f1SDimitry Andric               Section.Classes.emplace_back(
561fe6060f1SDimitry Andric                   copyString("_" + Symbol->getName().str()));
562fe6060f1SDimitry Andric             else
563fe6060f1SDimitry Andric               Section.Classes.emplace_back(Symbol->getName());
564fe6060f1SDimitry Andric             break;
565fe6060f1SDimitry Andric           case SymbolKind::ObjectiveCClassEHType:
566fe6060f1SDimitry Andric             if (File->getFileType() != FileType::TBD_V3)
567fe6060f1SDimitry Andric               Section.Symbols.emplace_back(
568fe6060f1SDimitry Andric                   copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str()));
569fe6060f1SDimitry Andric             else
570fe6060f1SDimitry Andric               Section.ClassEHs.emplace_back(Symbol->getName());
571fe6060f1SDimitry Andric             break;
572fe6060f1SDimitry Andric           case SymbolKind::ObjectiveCInstanceVariable:
573fe6060f1SDimitry Andric             if (File->getFileType() != FileType::TBD_V3)
574fe6060f1SDimitry Andric               Section.IVars.emplace_back(
575fe6060f1SDimitry Andric                   copyString("_" + Symbol->getName().str()));
576fe6060f1SDimitry Andric             else
577fe6060f1SDimitry Andric               Section.IVars.emplace_back(Symbol->getName());
578fe6060f1SDimitry Andric             break;
579fe6060f1SDimitry Andric           }
580fe6060f1SDimitry Andric         }
581fe6060f1SDimitry Andric         llvm::sort(Section.Symbols);
582fe6060f1SDimitry Andric         llvm::sort(Section.Classes);
583fe6060f1SDimitry Andric         llvm::sort(Section.ClassEHs);
584fe6060f1SDimitry Andric         llvm::sort(Section.IVars);
585fe6060f1SDimitry Andric         llvm::sort(Section.WeakRefSymbols);
586fe6060f1SDimitry Andric         Undefineds.emplace_back(std::move(Section));
587fe6060f1SDimitry Andric       }
588fe6060f1SDimitry Andric     }
589fe6060f1SDimitry Andric 
590fe6060f1SDimitry Andric     // TBD v1 - TBD v3 files only support one platform and several
591fe6060f1SDimitry Andric     // architectures. It is possible to have more than one platform for TBD v3
592fe6060f1SDimitry Andric     // files, but the architectures don't apply to all
593fe6060f1SDimitry Andric     // platforms, specifically to filter out the i386 slice from
594fe6060f1SDimitry Andric     // platform macCatalyst.
595fe6060f1SDimitry Andric     TargetList synthesizeTargets(ArchitectureSet Architectures,
596fe6060f1SDimitry Andric                                  const PlatformSet &Platforms) {
597fe6060f1SDimitry Andric       TargetList Targets;
598fe6060f1SDimitry Andric 
599fe6060f1SDimitry Andric       for (auto Platform : Platforms) {
600*04eeddc0SDimitry Andric         Platform = mapToPlatformType(Platform, Architectures.hasX86());
601fe6060f1SDimitry Andric 
602fe6060f1SDimitry Andric         for (const auto &&Architecture : Architectures) {
603*04eeddc0SDimitry Andric           if ((Architecture == AK_i386) && (Platform == PLATFORM_MACCATALYST))
604fe6060f1SDimitry Andric             continue;
605fe6060f1SDimitry Andric 
606fe6060f1SDimitry Andric           Targets.emplace_back(Architecture, Platform);
607fe6060f1SDimitry Andric         }
608fe6060f1SDimitry Andric       }
609fe6060f1SDimitry Andric       return Targets;
610fe6060f1SDimitry Andric     }
611fe6060f1SDimitry Andric 
612fe6060f1SDimitry Andric     const InterfaceFile *denormalize(IO &IO) {
613fe6060f1SDimitry Andric       auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
614fe6060f1SDimitry Andric       assert(Ctx);
615fe6060f1SDimitry Andric 
616fe6060f1SDimitry Andric       auto *File = new InterfaceFile;
617fe6060f1SDimitry Andric       File->setPath(Ctx->Path);
618fe6060f1SDimitry Andric       File->setFileType(Ctx->FileKind);
619fe6060f1SDimitry Andric       File->addTargets(synthesizeTargets(Architectures, Platforms));
620fe6060f1SDimitry Andric       for (auto &ID : UUIDs)
621fe6060f1SDimitry Andric         File->addUUID(ID.first, ID.second);
622fe6060f1SDimitry Andric       File->setInstallName(InstallName);
623fe6060f1SDimitry Andric       File->setCurrentVersion(CurrentVersion);
624fe6060f1SDimitry Andric       File->setCompatibilityVersion(CompatibilityVersion);
625fe6060f1SDimitry Andric       File->setSwiftABIVersion(SwiftABIVersion);
626fe6060f1SDimitry Andric       File->setObjCConstraint(ObjCConstraint);
627fe6060f1SDimitry Andric       for (const auto &Target : File->targets())
628fe6060f1SDimitry Andric         File->addParentUmbrella(Target, ParentUmbrella);
629fe6060f1SDimitry Andric 
630fe6060f1SDimitry Andric       if (Ctx->FileKind == FileType::TBD_V1) {
631fe6060f1SDimitry Andric         File->setTwoLevelNamespace();
632fe6060f1SDimitry Andric         File->setApplicationExtensionSafe();
633fe6060f1SDimitry Andric       } else {
634fe6060f1SDimitry Andric         File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
635fe6060f1SDimitry Andric         File->setApplicationExtensionSafe(
636fe6060f1SDimitry Andric             !(Flags & TBDFlags::NotApplicationExtensionSafe));
637fe6060f1SDimitry Andric         File->setInstallAPI(Flags & TBDFlags::InstallAPI);
638fe6060f1SDimitry Andric       }
639fe6060f1SDimitry Andric 
640fe6060f1SDimitry Andric       for (const auto &Section : Exports) {
641fe6060f1SDimitry Andric         const auto Targets =
642fe6060f1SDimitry Andric             synthesizeTargets(Section.Architectures, Platforms);
643fe6060f1SDimitry Andric 
644fe6060f1SDimitry Andric         for (const auto &Lib : Section.AllowableClients)
645fe6060f1SDimitry Andric           for (const auto &Target : Targets)
646fe6060f1SDimitry Andric             File->addAllowableClient(Lib, Target);
647fe6060f1SDimitry Andric 
648fe6060f1SDimitry Andric         for (const auto &Lib : Section.ReexportedLibraries)
649fe6060f1SDimitry Andric           for (const auto &Target : Targets)
650fe6060f1SDimitry Andric             File->addReexportedLibrary(Lib, Target);
651fe6060f1SDimitry Andric 
652fe6060f1SDimitry Andric         for (const auto &Symbol : Section.Symbols) {
653fe6060f1SDimitry Andric           if (Ctx->FileKind != FileType::TBD_V3 &&
654fe6060f1SDimitry Andric               Symbol.value.startswith("_OBJC_EHTYPE_$_"))
655fe6060f1SDimitry Andric             File->addSymbol(SymbolKind::ObjectiveCClassEHType,
656fe6060f1SDimitry Andric                             Symbol.value.drop_front(15), Targets);
657fe6060f1SDimitry Andric           else
658fe6060f1SDimitry Andric             File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets);
659fe6060f1SDimitry Andric         }
660fe6060f1SDimitry Andric         for (auto &Symbol : Section.Classes) {
661fe6060f1SDimitry Andric           auto Name = Symbol.value;
662fe6060f1SDimitry Andric           if (Ctx->FileKind != FileType::TBD_V3)
663fe6060f1SDimitry Andric             Name = Name.drop_front();
664fe6060f1SDimitry Andric           File->addSymbol(SymbolKind::ObjectiveCClass, Name, Targets);
665fe6060f1SDimitry Andric         }
666fe6060f1SDimitry Andric         for (auto &Symbol : Section.ClassEHs)
667fe6060f1SDimitry Andric           File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol, Targets);
668fe6060f1SDimitry Andric         for (auto &Symbol : Section.IVars) {
669fe6060f1SDimitry Andric           auto Name = Symbol.value;
670fe6060f1SDimitry Andric           if (Ctx->FileKind != FileType::TBD_V3)
671fe6060f1SDimitry Andric             Name = Name.drop_front();
672fe6060f1SDimitry Andric           File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name,
673fe6060f1SDimitry Andric                           Targets);
674fe6060f1SDimitry Andric         }
675fe6060f1SDimitry Andric         for (auto &Symbol : Section.WeakDefSymbols)
676fe6060f1SDimitry Andric           File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
677fe6060f1SDimitry Andric                           SymbolFlags::WeakDefined);
678fe6060f1SDimitry Andric         for (auto &Symbol : Section.TLVSymbols)
679fe6060f1SDimitry Andric           File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
680fe6060f1SDimitry Andric                           SymbolFlags::ThreadLocalValue);
681fe6060f1SDimitry Andric       }
682fe6060f1SDimitry Andric 
683fe6060f1SDimitry Andric       for (const auto &Section : Undefineds) {
684fe6060f1SDimitry Andric         const auto Targets =
685fe6060f1SDimitry Andric             synthesizeTargets(Section.Architectures, Platforms);
686fe6060f1SDimitry Andric         for (auto &Symbol : Section.Symbols) {
687fe6060f1SDimitry Andric           if (Ctx->FileKind != FileType::TBD_V3 &&
688fe6060f1SDimitry Andric               Symbol.value.startswith("_OBJC_EHTYPE_$_"))
689fe6060f1SDimitry Andric             File->addSymbol(SymbolKind::ObjectiveCClassEHType,
690fe6060f1SDimitry Andric                             Symbol.value.drop_front(15), Targets,
691fe6060f1SDimitry Andric                             SymbolFlags::Undefined);
692fe6060f1SDimitry Andric           else
693fe6060f1SDimitry Andric             File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
694fe6060f1SDimitry Andric                             SymbolFlags::Undefined);
695fe6060f1SDimitry Andric         }
696fe6060f1SDimitry Andric         for (auto &Symbol : Section.Classes) {
697fe6060f1SDimitry Andric           auto Name = Symbol.value;
698fe6060f1SDimitry Andric           if (Ctx->FileKind != FileType::TBD_V3)
699fe6060f1SDimitry Andric             Name = Name.drop_front();
700fe6060f1SDimitry Andric           File->addSymbol(SymbolKind::ObjectiveCClass, Name, Targets,
701fe6060f1SDimitry Andric                           SymbolFlags::Undefined);
702fe6060f1SDimitry Andric         }
703fe6060f1SDimitry Andric         for (auto &Symbol : Section.ClassEHs)
704fe6060f1SDimitry Andric           File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol, Targets,
705fe6060f1SDimitry Andric                           SymbolFlags::Undefined);
706fe6060f1SDimitry Andric         for (auto &Symbol : Section.IVars) {
707fe6060f1SDimitry Andric           auto Name = Symbol.value;
708fe6060f1SDimitry Andric           if (Ctx->FileKind != FileType::TBD_V3)
709fe6060f1SDimitry Andric             Name = Name.drop_front();
710fe6060f1SDimitry Andric           File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name, Targets,
711fe6060f1SDimitry Andric                           SymbolFlags::Undefined);
712fe6060f1SDimitry Andric         }
713fe6060f1SDimitry Andric         for (auto &Symbol : Section.WeakRefSymbols)
714fe6060f1SDimitry Andric           File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
715fe6060f1SDimitry Andric                           SymbolFlags::Undefined | SymbolFlags::WeakReferenced);
716fe6060f1SDimitry Andric       }
717fe6060f1SDimitry Andric 
718fe6060f1SDimitry Andric       return File;
719fe6060f1SDimitry Andric     }
720fe6060f1SDimitry Andric 
721fe6060f1SDimitry Andric     llvm::BumpPtrAllocator Allocator;
722fe6060f1SDimitry Andric     StringRef copyString(StringRef String) {
723fe6060f1SDimitry Andric       if (String.empty())
724fe6060f1SDimitry Andric         return {};
725fe6060f1SDimitry Andric 
726fe6060f1SDimitry Andric       void *Ptr = Allocator.Allocate(String.size(), 1);
727fe6060f1SDimitry Andric       memcpy(Ptr, String.data(), String.size());
728fe6060f1SDimitry Andric       return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
729fe6060f1SDimitry Andric     }
730fe6060f1SDimitry Andric 
731fe6060f1SDimitry Andric     std::vector<Architecture> Architectures;
732fe6060f1SDimitry Andric     std::vector<UUID> UUIDs;
733fe6060f1SDimitry Andric     PlatformSet Platforms;
734fe6060f1SDimitry Andric     StringRef InstallName;
735fe6060f1SDimitry Andric     PackedVersion CurrentVersion;
736fe6060f1SDimitry Andric     PackedVersion CompatibilityVersion;
737fe6060f1SDimitry Andric     SwiftVersion SwiftABIVersion{0};
738fe6060f1SDimitry Andric     ObjCConstraintType ObjCConstraint{ObjCConstraintType::None};
739fe6060f1SDimitry Andric     TBDFlags Flags{TBDFlags::None};
740fe6060f1SDimitry Andric     StringRef ParentUmbrella;
741fe6060f1SDimitry Andric     std::vector<ExportSection> Exports;
742fe6060f1SDimitry Andric     std::vector<UndefinedSection> Undefineds;
743fe6060f1SDimitry Andric   };
744fe6060f1SDimitry Andric 
745fe6060f1SDimitry Andric   static void setFileTypeForInput(TextAPIContext *Ctx, IO &IO) {
746fe6060f1SDimitry Andric     if (IO.mapTag("!tapi-tbd", false))
747fe6060f1SDimitry Andric       Ctx->FileKind = FileType::TBD_V4;
748fe6060f1SDimitry Andric     else if (IO.mapTag("!tapi-tbd-v3", false))
749fe6060f1SDimitry Andric       Ctx->FileKind = FileType::TBD_V3;
750fe6060f1SDimitry Andric     else if (IO.mapTag("!tapi-tbd-v2", false))
751fe6060f1SDimitry Andric       Ctx->FileKind = FileType::TBD_V2;
752fe6060f1SDimitry Andric     else if (IO.mapTag("!tapi-tbd-v1", false) ||
753fe6060f1SDimitry Andric              IO.mapTag("tag:yaml.org,2002:map", false))
754fe6060f1SDimitry Andric       Ctx->FileKind = FileType::TBD_V1;
755fe6060f1SDimitry Andric     else {
756fe6060f1SDimitry Andric       Ctx->FileKind = FileType::Invalid;
757fe6060f1SDimitry Andric       return;
758fe6060f1SDimitry Andric     }
759fe6060f1SDimitry Andric   }
760fe6060f1SDimitry Andric 
761fe6060f1SDimitry Andric   static void mapping(IO &IO, const InterfaceFile *&File) {
762fe6060f1SDimitry Andric     auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
763fe6060f1SDimitry Andric     assert((!Ctx || !IO.outputting() ||
764fe6060f1SDimitry Andric             (Ctx && Ctx->FileKind != FileType::Invalid)) &&
765fe6060f1SDimitry Andric            "File type is not set in YAML context");
766fe6060f1SDimitry Andric 
767fe6060f1SDimitry Andric     if (!IO.outputting()) {
768fe6060f1SDimitry Andric       setFileTypeForInput(Ctx, IO);
769fe6060f1SDimitry Andric       switch (Ctx->FileKind) {
770fe6060f1SDimitry Andric       default:
771fe6060f1SDimitry Andric         break;
772fe6060f1SDimitry Andric       case FileType::TBD_V4:
773fe6060f1SDimitry Andric         mapKeysToValuesV4(IO, File);
774fe6060f1SDimitry Andric         return;
775fe6060f1SDimitry Andric       case FileType::Invalid:
776fe6060f1SDimitry Andric         IO.setError("unsupported file type");
777fe6060f1SDimitry Andric         return;
778fe6060f1SDimitry Andric       }
779fe6060f1SDimitry Andric     } else {
780fe6060f1SDimitry Andric       // Set file type when writing.
781fe6060f1SDimitry Andric       switch (Ctx->FileKind) {
782fe6060f1SDimitry Andric       default:
783fe6060f1SDimitry Andric         llvm_unreachable("unexpected file type");
784fe6060f1SDimitry Andric       case FileType::TBD_V4:
785fe6060f1SDimitry Andric         mapKeysToValuesV4(IO, File);
786fe6060f1SDimitry Andric         return;
787fe6060f1SDimitry Andric       case FileType::TBD_V3:
788fe6060f1SDimitry Andric         IO.mapTag("!tapi-tbd-v3", true);
789fe6060f1SDimitry Andric         break;
790fe6060f1SDimitry Andric       case FileType::TBD_V2:
791fe6060f1SDimitry Andric         IO.mapTag("!tapi-tbd-v2", true);
792fe6060f1SDimitry Andric         break;
793fe6060f1SDimitry Andric       case FileType::TBD_V1:
794fe6060f1SDimitry Andric         // Don't write the tag into the .tbd file for TBD v1
795fe6060f1SDimitry Andric         break;
796fe6060f1SDimitry Andric       }
797fe6060f1SDimitry Andric     }
798fe6060f1SDimitry Andric     mapKeysToValues(Ctx->FileKind, IO, File);
799fe6060f1SDimitry Andric   }
800fe6060f1SDimitry Andric 
801fe6060f1SDimitry Andric   using SectionList = std::vector<SymbolSection>;
802fe6060f1SDimitry Andric   struct NormalizedTBD_V4 {
803fe6060f1SDimitry Andric     explicit NormalizedTBD_V4(IO &IO) {}
804fe6060f1SDimitry Andric     NormalizedTBD_V4(IO &IO, const InterfaceFile *&File) {
805fe6060f1SDimitry Andric       auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
806fe6060f1SDimitry Andric       assert(Ctx);
807fe6060f1SDimitry Andric       TBDVersion = Ctx->FileKind >> 1;
808fe6060f1SDimitry Andric       Targets.insert(Targets.begin(), File->targets().begin(),
809fe6060f1SDimitry Andric                      File->targets().end());
810fe6060f1SDimitry Andric       for (const auto &IT : File->uuids())
811fe6060f1SDimitry Andric         UUIDs.emplace_back(IT.first, IT.second);
812fe6060f1SDimitry Andric       InstallName = File->getInstallName();
813fe6060f1SDimitry Andric       CurrentVersion = File->getCurrentVersion();
814fe6060f1SDimitry Andric       CompatibilityVersion = File->getCompatibilityVersion();
815fe6060f1SDimitry Andric       SwiftABIVersion = File->getSwiftABIVersion();
816fe6060f1SDimitry Andric 
817fe6060f1SDimitry Andric       Flags = TBDFlags::None;
818fe6060f1SDimitry Andric       if (!File->isApplicationExtensionSafe())
819fe6060f1SDimitry Andric         Flags |= TBDFlags::NotApplicationExtensionSafe;
820fe6060f1SDimitry Andric 
821fe6060f1SDimitry Andric       if (!File->isTwoLevelNamespace())
822fe6060f1SDimitry Andric         Flags |= TBDFlags::FlatNamespace;
823fe6060f1SDimitry Andric 
824fe6060f1SDimitry Andric       if (File->isInstallAPI())
825fe6060f1SDimitry Andric         Flags |= TBDFlags::InstallAPI;
826fe6060f1SDimitry Andric 
827fe6060f1SDimitry Andric       {
828fe6060f1SDimitry Andric         std::map<std::string, TargetList> valueToTargetList;
829fe6060f1SDimitry Andric         for (const auto &it : File->umbrellas())
830fe6060f1SDimitry Andric           valueToTargetList[it.second].emplace_back(it.first);
831fe6060f1SDimitry Andric 
832fe6060f1SDimitry Andric         for (const auto &it : valueToTargetList) {
833fe6060f1SDimitry Andric           UmbrellaSection CurrentSection;
834fe6060f1SDimitry Andric           CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
835fe6060f1SDimitry Andric                                         it.second.begin(), it.second.end());
836fe6060f1SDimitry Andric           CurrentSection.Umbrella = it.first;
837fe6060f1SDimitry Andric           ParentUmbrellas.emplace_back(std::move(CurrentSection));
838fe6060f1SDimitry Andric         }
839fe6060f1SDimitry Andric       }
840fe6060f1SDimitry Andric 
841fe6060f1SDimitry Andric       assignTargetsToLibrary(File->allowableClients(), AllowableClients);
842fe6060f1SDimitry Andric       assignTargetsToLibrary(File->reexportedLibraries(), ReexportedLibraries);
843fe6060f1SDimitry Andric 
844fe6060f1SDimitry Andric       auto handleSymbols =
845fe6060f1SDimitry Andric           [](SectionList &CurrentSections,
846fe6060f1SDimitry Andric              InterfaceFile::const_filtered_symbol_range Symbols,
847fe6060f1SDimitry Andric              std::function<bool(const Symbol *)> Pred) {
848fe6060f1SDimitry Andric             std::set<TargetList> TargetSet;
849fe6060f1SDimitry Andric             std::map<const Symbol *, TargetList> SymbolToTargetList;
850fe6060f1SDimitry Andric             for (const auto *Symbol : Symbols) {
851fe6060f1SDimitry Andric               if (!Pred(Symbol))
852fe6060f1SDimitry Andric                 continue;
853fe6060f1SDimitry Andric               TargetList Targets(Symbol->targets());
854fe6060f1SDimitry Andric               SymbolToTargetList[Symbol] = Targets;
855fe6060f1SDimitry Andric               TargetSet.emplace(std::move(Targets));
856fe6060f1SDimitry Andric             }
857fe6060f1SDimitry Andric             for (const auto &TargetIDs : TargetSet) {
858fe6060f1SDimitry Andric               SymbolSection CurrentSection;
859fe6060f1SDimitry Andric               CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
860fe6060f1SDimitry Andric                                             TargetIDs.begin(), TargetIDs.end());
861fe6060f1SDimitry Andric 
862fe6060f1SDimitry Andric               for (const auto &IT : SymbolToTargetList) {
863fe6060f1SDimitry Andric                 if (IT.second != TargetIDs)
864fe6060f1SDimitry Andric                   continue;
865fe6060f1SDimitry Andric 
866fe6060f1SDimitry Andric                 const auto *Symbol = IT.first;
867fe6060f1SDimitry Andric                 switch (Symbol->getKind()) {
868fe6060f1SDimitry Andric                 case SymbolKind::GlobalSymbol:
869fe6060f1SDimitry Andric                   if (Symbol->isWeakDefined())
870fe6060f1SDimitry Andric                     CurrentSection.WeakSymbols.emplace_back(Symbol->getName());
871fe6060f1SDimitry Andric                   else if (Symbol->isThreadLocalValue())
872fe6060f1SDimitry Andric                     CurrentSection.TlvSymbols.emplace_back(Symbol->getName());
873fe6060f1SDimitry Andric                   else
874fe6060f1SDimitry Andric                     CurrentSection.Symbols.emplace_back(Symbol->getName());
875fe6060f1SDimitry Andric                   break;
876fe6060f1SDimitry Andric                 case SymbolKind::ObjectiveCClass:
877fe6060f1SDimitry Andric                   CurrentSection.Classes.emplace_back(Symbol->getName());
878fe6060f1SDimitry Andric                   break;
879fe6060f1SDimitry Andric                 case SymbolKind::ObjectiveCClassEHType:
880fe6060f1SDimitry Andric                   CurrentSection.ClassEHs.emplace_back(Symbol->getName());
881fe6060f1SDimitry Andric                   break;
882fe6060f1SDimitry Andric                 case SymbolKind::ObjectiveCInstanceVariable:
883fe6060f1SDimitry Andric                   CurrentSection.Ivars.emplace_back(Symbol->getName());
884fe6060f1SDimitry Andric                   break;
885fe6060f1SDimitry Andric                 }
886fe6060f1SDimitry Andric               }
887fe6060f1SDimitry Andric               sort(CurrentSection.Symbols);
888fe6060f1SDimitry Andric               sort(CurrentSection.Classes);
889fe6060f1SDimitry Andric               sort(CurrentSection.ClassEHs);
890fe6060f1SDimitry Andric               sort(CurrentSection.Ivars);
891fe6060f1SDimitry Andric               sort(CurrentSection.WeakSymbols);
892fe6060f1SDimitry Andric               sort(CurrentSection.TlvSymbols);
893fe6060f1SDimitry Andric               CurrentSections.emplace_back(std::move(CurrentSection));
894fe6060f1SDimitry Andric             }
895fe6060f1SDimitry Andric           };
896fe6060f1SDimitry Andric 
897fe6060f1SDimitry Andric       handleSymbols(Exports, File->exports(), [](const Symbol *Symbol) {
898fe6060f1SDimitry Andric         return !Symbol->isReexported();
899fe6060f1SDimitry Andric       });
900fe6060f1SDimitry Andric       handleSymbols(Reexports, File->exports(), [](const Symbol *Symbol) {
901fe6060f1SDimitry Andric         return Symbol->isReexported();
902fe6060f1SDimitry Andric       });
903fe6060f1SDimitry Andric       handleSymbols(Undefineds, File->undefineds(),
904fe6060f1SDimitry Andric                     [](const Symbol *Symbol) { return true; });
905fe6060f1SDimitry Andric     }
906fe6060f1SDimitry Andric 
907fe6060f1SDimitry Andric     const InterfaceFile *denormalize(IO &IO) {
908fe6060f1SDimitry Andric       auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
909fe6060f1SDimitry Andric       assert(Ctx);
910fe6060f1SDimitry Andric 
911fe6060f1SDimitry Andric       auto *File = new InterfaceFile;
912fe6060f1SDimitry Andric       File->setPath(Ctx->Path);
913fe6060f1SDimitry Andric       File->setFileType(Ctx->FileKind);
914fe6060f1SDimitry Andric       for (auto &id : UUIDs)
915fe6060f1SDimitry Andric         File->addUUID(id.TargetID, id.Value);
916fe6060f1SDimitry Andric       File->addTargets(Targets);
917fe6060f1SDimitry Andric       File->setInstallName(InstallName);
918fe6060f1SDimitry Andric       File->setCurrentVersion(CurrentVersion);
919fe6060f1SDimitry Andric       File->setCompatibilityVersion(CompatibilityVersion);
920fe6060f1SDimitry Andric       File->setSwiftABIVersion(SwiftABIVersion);
921fe6060f1SDimitry Andric       for (const auto &CurrentSection : ParentUmbrellas)
922fe6060f1SDimitry Andric         for (const auto &target : CurrentSection.Targets)
923fe6060f1SDimitry Andric           File->addParentUmbrella(target, CurrentSection.Umbrella);
924fe6060f1SDimitry Andric       File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
925fe6060f1SDimitry Andric       File->setApplicationExtensionSafe(
926fe6060f1SDimitry Andric           !(Flags & TBDFlags::NotApplicationExtensionSafe));
927fe6060f1SDimitry Andric       File->setInstallAPI(Flags & TBDFlags::InstallAPI);
928fe6060f1SDimitry Andric 
929fe6060f1SDimitry Andric       for (const auto &CurrentSection : AllowableClients) {
930fe6060f1SDimitry Andric         for (const auto &lib : CurrentSection.Values)
931fe6060f1SDimitry Andric           for (const auto &Target : CurrentSection.Targets)
932fe6060f1SDimitry Andric             File->addAllowableClient(lib, Target);
933fe6060f1SDimitry Andric       }
934fe6060f1SDimitry Andric 
935fe6060f1SDimitry Andric       for (const auto &CurrentSection : ReexportedLibraries) {
936fe6060f1SDimitry Andric         for (const auto &Lib : CurrentSection.Values)
937fe6060f1SDimitry Andric           for (const auto &Target : CurrentSection.Targets)
938fe6060f1SDimitry Andric             File->addReexportedLibrary(Lib, Target);
939fe6060f1SDimitry Andric       }
940fe6060f1SDimitry Andric 
941fe6060f1SDimitry Andric       auto handleSymbols = [File](const SectionList &CurrentSections,
942fe6060f1SDimitry Andric                                   SymbolFlags Flag = SymbolFlags::None) {
943fe6060f1SDimitry Andric         for (const auto &CurrentSection : CurrentSections) {
944fe6060f1SDimitry Andric           for (auto &sym : CurrentSection.Symbols)
945fe6060f1SDimitry Andric             File->addSymbol(SymbolKind::GlobalSymbol, sym,
946fe6060f1SDimitry Andric                             CurrentSection.Targets, Flag);
947fe6060f1SDimitry Andric 
948fe6060f1SDimitry Andric           for (auto &sym : CurrentSection.Classes)
949fe6060f1SDimitry Andric             File->addSymbol(SymbolKind::ObjectiveCClass, sym,
950fe6060f1SDimitry Andric                             CurrentSection.Targets);
951fe6060f1SDimitry Andric 
952fe6060f1SDimitry Andric           for (auto &sym : CurrentSection.ClassEHs)
953fe6060f1SDimitry Andric             File->addSymbol(SymbolKind::ObjectiveCClassEHType, sym,
954fe6060f1SDimitry Andric                             CurrentSection.Targets);
955fe6060f1SDimitry Andric 
956fe6060f1SDimitry Andric           for (auto &sym : CurrentSection.Ivars)
957fe6060f1SDimitry Andric             File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, sym,
958fe6060f1SDimitry Andric                             CurrentSection.Targets);
959fe6060f1SDimitry Andric 
960fe6060f1SDimitry Andric           for (auto &sym : CurrentSection.WeakSymbols)
961fe6060f1SDimitry Andric             File->addSymbol(SymbolKind::GlobalSymbol, sym,
962fe6060f1SDimitry Andric                             CurrentSection.Targets, SymbolFlags::WeakDefined);
963fe6060f1SDimitry Andric 
964fe6060f1SDimitry Andric           for (auto &sym : CurrentSection.TlvSymbols)
965fe6060f1SDimitry Andric             File->addSymbol(SymbolKind::GlobalSymbol, sym,
966fe6060f1SDimitry Andric                             CurrentSection.Targets,
967fe6060f1SDimitry Andric                             SymbolFlags::ThreadLocalValue);
968fe6060f1SDimitry Andric         }
969fe6060f1SDimitry Andric       };
970fe6060f1SDimitry Andric 
971fe6060f1SDimitry Andric       handleSymbols(Exports);
972fe6060f1SDimitry Andric       handleSymbols(Reexports, SymbolFlags::Rexported);
973fe6060f1SDimitry Andric       handleSymbols(Undefineds, SymbolFlags::Undefined);
974fe6060f1SDimitry Andric 
975fe6060f1SDimitry Andric       return File;
976fe6060f1SDimitry Andric     }
977fe6060f1SDimitry Andric 
978fe6060f1SDimitry Andric     unsigned TBDVersion;
979fe6060f1SDimitry Andric     std::vector<UUIDv4> UUIDs;
980fe6060f1SDimitry Andric     TargetList Targets;
981fe6060f1SDimitry Andric     StringRef InstallName;
982fe6060f1SDimitry Andric     PackedVersion CurrentVersion;
983fe6060f1SDimitry Andric     PackedVersion CompatibilityVersion;
984fe6060f1SDimitry Andric     SwiftVersion SwiftABIVersion{0};
985fe6060f1SDimitry Andric     std::vector<MetadataSection> AllowableClients;
986fe6060f1SDimitry Andric     std::vector<MetadataSection> ReexportedLibraries;
987fe6060f1SDimitry Andric     TBDFlags Flags{TBDFlags::None};
988fe6060f1SDimitry Andric     std::vector<UmbrellaSection> ParentUmbrellas;
989fe6060f1SDimitry Andric     SectionList Exports;
990fe6060f1SDimitry Andric     SectionList Reexports;
991fe6060f1SDimitry Andric     SectionList Undefineds;
992fe6060f1SDimitry Andric 
993fe6060f1SDimitry Andric   private:
994fe6060f1SDimitry Andric     void assignTargetsToLibrary(const std::vector<InterfaceFileRef> &Libraries,
995fe6060f1SDimitry Andric                                 std::vector<MetadataSection> &Section) {
996fe6060f1SDimitry Andric       std::set<TargetList> targetSet;
997fe6060f1SDimitry Andric       std::map<const InterfaceFileRef *, TargetList> valueToTargetList;
998fe6060f1SDimitry Andric       for (const auto &library : Libraries) {
999fe6060f1SDimitry Andric         TargetList targets(library.targets());
1000fe6060f1SDimitry Andric         valueToTargetList[&library] = targets;
1001fe6060f1SDimitry Andric         targetSet.emplace(std::move(targets));
1002fe6060f1SDimitry Andric       }
1003fe6060f1SDimitry Andric 
1004fe6060f1SDimitry Andric       for (const auto &targets : targetSet) {
1005fe6060f1SDimitry Andric         MetadataSection CurrentSection;
1006fe6060f1SDimitry Andric         CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
1007fe6060f1SDimitry Andric                                       targets.begin(), targets.end());
1008fe6060f1SDimitry Andric 
1009fe6060f1SDimitry Andric         for (const auto &it : valueToTargetList) {
1010fe6060f1SDimitry Andric           if (it.second != targets)
1011fe6060f1SDimitry Andric             continue;
1012fe6060f1SDimitry Andric 
1013fe6060f1SDimitry Andric           CurrentSection.Values.emplace_back(it.first->getInstallName());
1014fe6060f1SDimitry Andric         }
1015fe6060f1SDimitry Andric         llvm::sort(CurrentSection.Values);
1016fe6060f1SDimitry Andric         Section.emplace_back(std::move(CurrentSection));
1017fe6060f1SDimitry Andric       }
1018fe6060f1SDimitry Andric     }
1019fe6060f1SDimitry Andric   };
1020fe6060f1SDimitry Andric 
1021fe6060f1SDimitry Andric   static void mapKeysToValues(FileType FileKind, IO &IO,
1022fe6060f1SDimitry Andric                               const InterfaceFile *&File) {
1023fe6060f1SDimitry Andric     MappingNormalization<NormalizedTBD, const InterfaceFile *> Keys(IO, File);
1024fe6060f1SDimitry Andric     IO.mapRequired("archs", Keys->Architectures);
1025fe6060f1SDimitry Andric     if (FileKind != FileType::TBD_V1)
1026fe6060f1SDimitry Andric       IO.mapOptional("uuids", Keys->UUIDs);
1027fe6060f1SDimitry Andric     IO.mapRequired("platform", Keys->Platforms);
1028fe6060f1SDimitry Andric     if (FileKind != FileType::TBD_V1)
1029fe6060f1SDimitry Andric       IO.mapOptional("flags", Keys->Flags, TBDFlags::None);
1030fe6060f1SDimitry Andric     IO.mapRequired("install-name", Keys->InstallName);
1031fe6060f1SDimitry Andric     IO.mapOptional("current-version", Keys->CurrentVersion,
1032fe6060f1SDimitry Andric                    PackedVersion(1, 0, 0));
1033fe6060f1SDimitry Andric     IO.mapOptional("compatibility-version", Keys->CompatibilityVersion,
1034fe6060f1SDimitry Andric                    PackedVersion(1, 0, 0));
1035fe6060f1SDimitry Andric     if (FileKind != FileType::TBD_V3)
1036fe6060f1SDimitry Andric       IO.mapOptional("swift-version", Keys->SwiftABIVersion, SwiftVersion(0));
1037fe6060f1SDimitry Andric     else
1038fe6060f1SDimitry Andric       IO.mapOptional("swift-abi-version", Keys->SwiftABIVersion,
1039fe6060f1SDimitry Andric                      SwiftVersion(0));
1040fe6060f1SDimitry Andric     IO.mapOptional("objc-constraint", Keys->ObjCConstraint,
1041fe6060f1SDimitry Andric                    (FileKind == FileType::TBD_V1)
1042fe6060f1SDimitry Andric                        ? ObjCConstraintType::None
1043fe6060f1SDimitry Andric                        : ObjCConstraintType::Retain_Release);
1044fe6060f1SDimitry Andric     if (FileKind != FileType::TBD_V1)
1045fe6060f1SDimitry Andric       IO.mapOptional("parent-umbrella", Keys->ParentUmbrella, StringRef());
1046fe6060f1SDimitry Andric     IO.mapOptional("exports", Keys->Exports);
1047fe6060f1SDimitry Andric     if (FileKind != FileType::TBD_V1)
1048fe6060f1SDimitry Andric       IO.mapOptional("undefineds", Keys->Undefineds);
1049fe6060f1SDimitry Andric   }
1050fe6060f1SDimitry Andric 
1051fe6060f1SDimitry Andric   static void mapKeysToValuesV4(IO &IO, const InterfaceFile *&File) {
1052fe6060f1SDimitry Andric     MappingNormalization<NormalizedTBD_V4, const InterfaceFile *> Keys(IO,
1053fe6060f1SDimitry Andric                                                                        File);
1054fe6060f1SDimitry Andric     IO.mapTag("!tapi-tbd", true);
1055fe6060f1SDimitry Andric     IO.mapRequired("tbd-version", Keys->TBDVersion);
1056fe6060f1SDimitry Andric     IO.mapRequired("targets", Keys->Targets);
1057fe6060f1SDimitry Andric     IO.mapOptional("uuids", Keys->UUIDs);
1058fe6060f1SDimitry Andric     IO.mapOptional("flags", Keys->Flags, TBDFlags::None);
1059fe6060f1SDimitry Andric     IO.mapRequired("install-name", Keys->InstallName);
1060fe6060f1SDimitry Andric     IO.mapOptional("current-version", Keys->CurrentVersion,
1061fe6060f1SDimitry Andric                    PackedVersion(1, 0, 0));
1062fe6060f1SDimitry Andric     IO.mapOptional("compatibility-version", Keys->CompatibilityVersion,
1063fe6060f1SDimitry Andric                    PackedVersion(1, 0, 0));
1064fe6060f1SDimitry Andric     IO.mapOptional("swift-abi-version", Keys->SwiftABIVersion, SwiftVersion(0));
1065fe6060f1SDimitry Andric     IO.mapOptional("parent-umbrella", Keys->ParentUmbrellas);
1066fe6060f1SDimitry Andric     auto OptionKind = MetadataSection::Option::Clients;
1067fe6060f1SDimitry Andric     IO.mapOptionalWithContext("allowable-clients", Keys->AllowableClients,
1068fe6060f1SDimitry Andric                               OptionKind);
1069fe6060f1SDimitry Andric     OptionKind = MetadataSection::Option::Libraries;
1070fe6060f1SDimitry Andric     IO.mapOptionalWithContext("reexported-libraries", Keys->ReexportedLibraries,
1071fe6060f1SDimitry Andric                               OptionKind);
1072fe6060f1SDimitry Andric     IO.mapOptional("exports", Keys->Exports);
1073fe6060f1SDimitry Andric     IO.mapOptional("reexports", Keys->Reexports);
1074fe6060f1SDimitry Andric     IO.mapOptional("undefineds", Keys->Undefineds);
1075fe6060f1SDimitry Andric   }
1076fe6060f1SDimitry Andric };
1077fe6060f1SDimitry Andric 
1078fe6060f1SDimitry Andric template <>
1079fe6060f1SDimitry Andric struct DocumentListTraits<std::vector<const MachO::InterfaceFile *>> {
1080fe6060f1SDimitry Andric   static size_t size(IO &IO, std::vector<const MachO::InterfaceFile *> &Seq) {
1081fe6060f1SDimitry Andric     return Seq.size();
1082fe6060f1SDimitry Andric   }
1083fe6060f1SDimitry Andric   static const InterfaceFile *&
1084fe6060f1SDimitry Andric   element(IO &IO, std::vector<const InterfaceFile *> &Seq, size_t Index) {
1085fe6060f1SDimitry Andric     if (Index >= Seq.size())
1086fe6060f1SDimitry Andric       Seq.resize(Index + 1);
1087fe6060f1SDimitry Andric     return Seq[Index];
1088fe6060f1SDimitry Andric   }
1089fe6060f1SDimitry Andric };
1090fe6060f1SDimitry Andric 
1091fe6060f1SDimitry Andric } // end namespace yaml.
1092fe6060f1SDimitry Andric } // namespace llvm
1093fe6060f1SDimitry Andric 
1094fe6060f1SDimitry Andric static void DiagHandler(const SMDiagnostic &Diag, void *Context) {
1095fe6060f1SDimitry Andric   auto *File = static_cast<TextAPIContext *>(Context);
1096fe6060f1SDimitry Andric   SmallString<1024> Message;
1097fe6060f1SDimitry Andric   raw_svector_ostream S(Message);
1098fe6060f1SDimitry Andric 
1099fe6060f1SDimitry Andric   SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), File->Path,
1100fe6060f1SDimitry Andric                        Diag.getLineNo(), Diag.getColumnNo(), Diag.getKind(),
1101fe6060f1SDimitry Andric                        Diag.getMessage(), Diag.getLineContents(),
1102fe6060f1SDimitry Andric                        Diag.getRanges(), Diag.getFixIts());
1103fe6060f1SDimitry Andric 
1104fe6060f1SDimitry Andric   NewDiag.print(nullptr, S);
1105fe6060f1SDimitry Andric   File->ErrorMessage = ("malformed file\n" + Message).str();
1106fe6060f1SDimitry Andric }
1107fe6060f1SDimitry Andric 
1108fe6060f1SDimitry Andric Expected<std::unique_ptr<InterfaceFile>>
1109fe6060f1SDimitry Andric TextAPIReader::get(MemoryBufferRef InputBuffer) {
1110fe6060f1SDimitry Andric   TextAPIContext Ctx;
1111fe6060f1SDimitry Andric   Ctx.Path = std::string(InputBuffer.getBufferIdentifier());
1112fe6060f1SDimitry Andric   yaml::Input YAMLIn(InputBuffer.getBuffer(), &Ctx, DiagHandler, &Ctx);
1113fe6060f1SDimitry Andric 
1114fe6060f1SDimitry Andric   // Fill vector with interface file objects created by parsing the YAML file.
1115fe6060f1SDimitry Andric   std::vector<const InterfaceFile *> Files;
1116fe6060f1SDimitry Andric   YAMLIn >> Files;
1117fe6060f1SDimitry Andric 
1118fe6060f1SDimitry Andric   // YAMLIn dynamically allocates for Interface file and in case of error,
1119fe6060f1SDimitry Andric   // memory leak will occur unless wrapped around unique_ptr
1120fe6060f1SDimitry Andric   auto File = std::unique_ptr<InterfaceFile>(
1121fe6060f1SDimitry Andric       const_cast<InterfaceFile *>(Files.front()));
1122fe6060f1SDimitry Andric 
1123349cc55cSDimitry Andric   for (const InterfaceFile *FI : llvm::drop_begin(Files))
1124fe6060f1SDimitry Andric     File->addDocument(
1125349cc55cSDimitry Andric         std::shared_ptr<InterfaceFile>(const_cast<InterfaceFile *>(FI)));
1126fe6060f1SDimitry Andric 
1127fe6060f1SDimitry Andric   if (YAMLIn.error())
1128fe6060f1SDimitry Andric     return make_error<StringError>(Ctx.ErrorMessage, YAMLIn.error());
1129fe6060f1SDimitry Andric 
1130fe6060f1SDimitry Andric   return std::move(File);
1131fe6060f1SDimitry Andric }
1132fe6060f1SDimitry Andric 
1133fe6060f1SDimitry Andric Error TextAPIWriter::writeToStream(raw_ostream &OS, const InterfaceFile &File) {
1134fe6060f1SDimitry Andric   TextAPIContext Ctx;
1135fe6060f1SDimitry Andric   Ctx.Path = std::string(File.getPath());
1136fe6060f1SDimitry Andric   Ctx.FileKind = File.getFileType();
1137fe6060f1SDimitry Andric   llvm::yaml::Output YAMLOut(OS, &Ctx, /*WrapColumn=*/80);
1138fe6060f1SDimitry Andric 
1139fe6060f1SDimitry Andric   std::vector<const InterfaceFile *> Files;
1140fe6060f1SDimitry Andric   Files.emplace_back(&File);
1141fe6060f1SDimitry Andric 
1142fe6060f1SDimitry Andric   for (auto Document : File.documents())
1143fe6060f1SDimitry Andric     Files.emplace_back(Document.get());
1144fe6060f1SDimitry Andric 
1145fe6060f1SDimitry Andric   // Stream out yaml.
1146fe6060f1SDimitry Andric   YAMLOut << Files;
1147fe6060f1SDimitry Andric 
1148fe6060f1SDimitry Andric   return Error::success();
1149fe6060f1SDimitry Andric }
1150