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