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