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