llvm-project

Форк
0
/
TextStub.cpp 
1164 строки · 44.5 Кб
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

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.