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