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