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