10116d04dSCyndy Ishida //===- TextStub.cpp -------------------------------------------------------===//
20116d04dSCyndy Ishida //
30116d04dSCyndy Ishida // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40116d04dSCyndy Ishida // See https://llvm.org/LICENSE.txt for license information.
50116d04dSCyndy Ishida // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60116d04dSCyndy Ishida //
70116d04dSCyndy Ishida //===----------------------------------------------------------------------===//
80116d04dSCyndy Ishida //
90116d04dSCyndy Ishida // Implements the text stub file reader/writer.
100116d04dSCyndy Ishida //
110116d04dSCyndy Ishida //===----------------------------------------------------------------------===//
120116d04dSCyndy Ishida 
130116d04dSCyndy Ishida #include "TextAPIContext.h"
140116d04dSCyndy Ishida #include "TextStubCommon.h"
150116d04dSCyndy Ishida #include "llvm/ADT/BitmaskEnum.h"
160116d04dSCyndy Ishida #include "llvm/ADT/SmallString.h"
170116d04dSCyndy Ishida #include "llvm/ADT/StringRef.h"
180116d04dSCyndy Ishida #include "llvm/Support/Allocator.h"
190116d04dSCyndy Ishida #include "llvm/Support/SourceMgr.h"
200116d04dSCyndy Ishida #include "llvm/Support/YAMLTraits.h"
210116d04dSCyndy Ishida #include "llvm/Support/raw_ostream.h"
220116d04dSCyndy Ishida #include "llvm/TextAPI/Architecture.h"
230116d04dSCyndy Ishida #include "llvm/TextAPI/ArchitectureSet.h"
240116d04dSCyndy Ishida #include "llvm/TextAPI/InterfaceFile.h"
250116d04dSCyndy Ishida #include "llvm/TextAPI/PackedVersion.h"
260116d04dSCyndy Ishida #include "llvm/TextAPI/TextAPIReader.h"
270116d04dSCyndy Ishida #include "llvm/TextAPI/TextAPIWriter.h"
280116d04dSCyndy Ishida #include <algorithm>
290116d04dSCyndy Ishida #include <set>
300116d04dSCyndy Ishida 
310116d04dSCyndy Ishida // clang-format off
320116d04dSCyndy Ishida /*
330116d04dSCyndy Ishida 
340116d04dSCyndy Ishida  YAML Format specification.
350116d04dSCyndy Ishida 
360116d04dSCyndy Ishida  The TBD v1 format only support two level address libraries and is per
370116d04dSCyndy Ishida  definition application extension safe.
380116d04dSCyndy Ishida 
390116d04dSCyndy Ishida ---                              # the tag !tapi-tbd-v1 is optional and
400116d04dSCyndy Ishida                                  # shouldn't be emitted to support older linker.
410116d04dSCyndy Ishida archs: [ armv7, armv7s, arm64 ]  # the list of architecture slices that are
420116d04dSCyndy Ishida                                  # supported by this file.
430116d04dSCyndy Ishida platform: ios                    # Specifies the platform (macosx, ios, etc)
440116d04dSCyndy Ishida install-name: /u/l/libfoo.dylib  #
450116d04dSCyndy Ishida current-version: 1.2.3           # Optional: defaults to 1.0
460116d04dSCyndy Ishida compatibility-version: 1.0       # Optional: defaults to 1.0
470116d04dSCyndy Ishida swift-version: 0                 # Optional: defaults to 0
480116d04dSCyndy Ishida objc-constraint: none            # Optional: defaults to none
490116d04dSCyndy Ishida exports:                         # List of export sections
500116d04dSCyndy Ishida ...
510116d04dSCyndy Ishida 
520116d04dSCyndy Ishida Each export section is defined as following:
530116d04dSCyndy Ishida 
540116d04dSCyndy Ishida  - archs: [ arm64 ]                   # the list of architecture slices
550116d04dSCyndy Ishida    allowed-clients: [ client ]        # Optional: List of clients
560116d04dSCyndy Ishida    re-exports: [ ]                    # Optional: List of re-exports
570116d04dSCyndy Ishida    symbols: [ _sym ]                  # Optional: List of symbols
580116d04dSCyndy Ishida    objc-classes: []                   # Optional: List of Objective-C classes
590116d04dSCyndy Ishida    objc-ivars: []                     # Optional: List of Objective C Instance
600116d04dSCyndy Ishida                                       #           Variables
610116d04dSCyndy Ishida    weak-def-symbols: []               # Optional: List of weak defined symbols
620116d04dSCyndy Ishida    thread-local-symbols: []           # Optional: List of thread local symbols
630116d04dSCyndy Ishida */
640116d04dSCyndy Ishida 
650116d04dSCyndy Ishida /*
660116d04dSCyndy Ishida 
670116d04dSCyndy Ishida  YAML Format specification.
680116d04dSCyndy Ishida 
690116d04dSCyndy Ishida --- !tapi-tbd-v2
700116d04dSCyndy Ishida archs: [ armv7, armv7s, arm64 ]  # the list of architecture slices that are
710116d04dSCyndy Ishida                                  # supported by this file.
720116d04dSCyndy Ishida uuids: [ armv7:... ]             # Optional: List of architecture and UUID pairs.
730116d04dSCyndy Ishida platform: ios                    # Specifies the platform (macosx, ios, etc)
740116d04dSCyndy Ishida flags: []                        # Optional:
750116d04dSCyndy Ishida install-name: /u/l/libfoo.dylib  #
760116d04dSCyndy Ishida current-version: 1.2.3           # Optional: defaults to 1.0
770116d04dSCyndy Ishida compatibility-version: 1.0       # Optional: defaults to 1.0
780116d04dSCyndy Ishida swift-version: 0                 # Optional: defaults to 0
790116d04dSCyndy Ishida objc-constraint: retain_release  # Optional: defaults to retain_release
800116d04dSCyndy Ishida parent-umbrella:                 # Optional:
810116d04dSCyndy Ishida exports:                         # List of export sections
820116d04dSCyndy Ishida ...
830116d04dSCyndy Ishida undefineds:                      # List of undefineds sections
840116d04dSCyndy Ishida ...
850116d04dSCyndy Ishida 
860116d04dSCyndy Ishida Each export section is defined as following:
870116d04dSCyndy Ishida 
880116d04dSCyndy Ishida - archs: [ arm64 ]                   # the list of architecture slices
890116d04dSCyndy Ishida   allowed-clients: [ client ]        # Optional: List of clients
900116d04dSCyndy Ishida   re-exports: [ ]                    # Optional: List of re-exports
910116d04dSCyndy Ishida   symbols: [ _sym ]                  # Optional: List of symbols
920116d04dSCyndy Ishida   objc-classes: []                   # Optional: List of Objective-C classes
930116d04dSCyndy Ishida   objc-ivars: []                     # Optional: List of Objective C Instance
940116d04dSCyndy Ishida                                      #           Variables
950116d04dSCyndy Ishida   weak-def-symbols: []               # Optional: List of weak defined symbols
960116d04dSCyndy Ishida   thread-local-symbols: []           # Optional: List of thread local symbols
970116d04dSCyndy Ishida 
980116d04dSCyndy Ishida Each undefineds section is defined as following:
990116d04dSCyndy Ishida - archs: [ arm64 ]     # the list of architecture slices
1000116d04dSCyndy Ishida   symbols: [ _sym ]    # Optional: List of symbols
1010116d04dSCyndy Ishida   objc-classes: []     # Optional: List of Objective-C classes
1020116d04dSCyndy Ishida   objc-ivars: []       # Optional: List of Objective C Instance Variables
1030116d04dSCyndy Ishida   weak-ref-symbols: [] # Optional: List of weak defined symbols
1040116d04dSCyndy Ishida */
1050116d04dSCyndy Ishida 
1060116d04dSCyndy Ishida /*
1070116d04dSCyndy Ishida 
1080116d04dSCyndy Ishida  YAML Format specification.
1090116d04dSCyndy Ishida 
1100116d04dSCyndy Ishida --- !tapi-tbd-v3
1110116d04dSCyndy Ishida archs: [ armv7, armv7s, arm64 ]  # the list of architecture slices that are
1120116d04dSCyndy Ishida                                  # supported by this file.
1130116d04dSCyndy Ishida uuids: [ armv7:... ]             # Optional: List of architecture and UUID pairs.
1140116d04dSCyndy Ishida platform: ios                    # Specifies the platform (macosx, ios, etc)
1150116d04dSCyndy Ishida flags: []                        # Optional:
1160116d04dSCyndy Ishida install-name: /u/l/libfoo.dylib  #
1170116d04dSCyndy Ishida current-version: 1.2.3           # Optional: defaults to 1.0
1180116d04dSCyndy Ishida compatibility-version: 1.0       # Optional: defaults to 1.0
1190116d04dSCyndy Ishida swift-abi-version: 0             # Optional: defaults to 0
1200116d04dSCyndy Ishida objc-constraint: retain_release  # Optional: defaults to retain_release
1210116d04dSCyndy Ishida parent-umbrella:                 # Optional:
1220116d04dSCyndy Ishida exports:                         # List of export sections
1230116d04dSCyndy Ishida ...
1240116d04dSCyndy Ishida undefineds:                      # List of undefineds sections
1250116d04dSCyndy Ishida ...
1260116d04dSCyndy Ishida 
1270116d04dSCyndy Ishida Each export section is defined as following:
1280116d04dSCyndy Ishida 
1290116d04dSCyndy Ishida - archs: [ arm64 ]                   # the list of architecture slices
1300116d04dSCyndy Ishida   allowed-clients: [ client ]        # Optional: List of clients
1310116d04dSCyndy Ishida   re-exports: [ ]                    # Optional: List of re-exports
1320116d04dSCyndy Ishida   symbols: [ _sym ]                  # Optional: List of symbols
1330116d04dSCyndy Ishida   objc-classes: []                   # Optional: List of Objective-C classes
1340116d04dSCyndy Ishida   objc-eh-types: []                  # Optional: List of Objective-C classes
1350116d04dSCyndy Ishida                                      #           with EH
1360116d04dSCyndy Ishida   objc-ivars: []                     # Optional: List of Objective C Instance
1370116d04dSCyndy Ishida                                      #           Variables
1380116d04dSCyndy Ishida   weak-def-symbols: []               # Optional: List of weak defined symbols
1390116d04dSCyndy Ishida   thread-local-symbols: []           # Optional: List of thread local symbols
1400116d04dSCyndy Ishida 
1410116d04dSCyndy Ishida Each undefineds section is defined as following:
1420116d04dSCyndy Ishida - archs: [ arm64 ]     # the list of architecture slices
1430116d04dSCyndy Ishida   symbols: [ _sym ]    # Optional: List of symbols
1440116d04dSCyndy Ishida   objc-classes: []     # Optional: List of Objective-C classes
1450116d04dSCyndy Ishida   objc-eh-types: []                  # Optional: List of Objective-C classes
1460116d04dSCyndy Ishida                                      #           with EH
1470116d04dSCyndy Ishida   objc-ivars: []       # Optional: List of Objective C Instance Variables
1480116d04dSCyndy Ishida   weak-ref-symbols: [] # Optional: List of weak defined symbols
1490116d04dSCyndy Ishida */
1500116d04dSCyndy Ishida 
1510116d04dSCyndy Ishida /*
1520116d04dSCyndy Ishida 
1530116d04dSCyndy Ishida  YAML Format specification.
1540116d04dSCyndy Ishida 
1550116d04dSCyndy Ishida --- !tapi-tbd
1560116d04dSCyndy Ishida tbd-version: 4                              # The tbd version for format
1570116d04dSCyndy Ishida targets: [ armv7-ios, x86_64-maccatalyst ]  # The list of applicable tapi supported target triples
1580116d04dSCyndy Ishida uuids:                                      # Optional: List of target and UUID pairs.
1590116d04dSCyndy Ishida   - target: armv7-ios
1600116d04dSCyndy Ishida     value: ...
1610116d04dSCyndy Ishida   - target: x86_64-maccatalyst
1620116d04dSCyndy Ishida     value: ...
1630116d04dSCyndy Ishida flags: []                        # Optional:
1640116d04dSCyndy Ishida install-name: /u/l/libfoo.dylib  #
1650116d04dSCyndy Ishida current-version: 1.2.3           # Optional: defaults to 1.0
1660116d04dSCyndy Ishida compatibility-version: 1.0       # Optional: defaults to 1.0
1670116d04dSCyndy Ishida swift-abi-version: 0             # Optional: defaults to 0
1680116d04dSCyndy Ishida parent-umbrella:                 # Optional:
1690116d04dSCyndy Ishida allowable-clients:
1700116d04dSCyndy Ishida   - targets: [ armv7-ios ]       # Optional:
1710116d04dSCyndy Ishida     clients: [ clientA ]
1720116d04dSCyndy Ishida exports:                         # List of export sections
1730116d04dSCyndy Ishida ...
1740116d04dSCyndy Ishida re-exports:                      # List of reexport sections
1750116d04dSCyndy Ishida ...
1760116d04dSCyndy Ishida undefineds:                      # List of undefineds sections
1770116d04dSCyndy Ishida ...
1780116d04dSCyndy Ishida 
1790116d04dSCyndy Ishida Each export and reexport  section is defined as following:
1800116d04dSCyndy Ishida 
1810116d04dSCyndy Ishida - targets: [ arm64-macos ]                        # The list of target triples associated with symbols
1820116d04dSCyndy Ishida   symbols: [ _symA ]                              # Optional: List of symbols
1830116d04dSCyndy Ishida   objc-classes: []                                # Optional: List of Objective-C classes
1840116d04dSCyndy Ishida   objc-eh-types: []                               # Optional: List of Objective-C classes
1850116d04dSCyndy Ishida                                                   #           with EH
1860116d04dSCyndy Ishida   objc-ivars: []                                  # Optional: List of Objective C Instance
1870116d04dSCyndy Ishida                                                   #           Variables
1880116d04dSCyndy Ishida   weak-symbols: []                                # Optional: List of weak defined symbols
1890116d04dSCyndy Ishida   thread-local-symbols: []                        # Optional: List of thread local symbols
1900116d04dSCyndy Ishida - targets: [ arm64-macos, x86_64-maccatalyst ]    # Optional: Targets for applicable additional symbols
1910116d04dSCyndy Ishida   symbols: [ _symB ]                              # Optional: List of symbols
1920116d04dSCyndy Ishida 
1930116d04dSCyndy Ishida Each undefineds section is defined as following:
1940116d04dSCyndy Ishida - targets: [ arm64-macos ]    # The list of target triples associated with symbols
1950116d04dSCyndy Ishida   symbols: [ _symC ]          # Optional: List of symbols
1960116d04dSCyndy Ishida   objc-classes: []            # Optional: List of Objective-C classes
1970116d04dSCyndy Ishida   objc-eh-types: []           # Optional: List of Objective-C classes
1980116d04dSCyndy Ishida                               #           with EH
1990116d04dSCyndy Ishida   objc-ivars: []              # Optional: List of Objective C Instance Variables
2000116d04dSCyndy Ishida   weak-symbols: []            # Optional: List of weak defined symbols
2010116d04dSCyndy Ishida */
2020116d04dSCyndy Ishida // clang-format on
2030116d04dSCyndy Ishida 
2040116d04dSCyndy Ishida using namespace llvm;
2050116d04dSCyndy Ishida using namespace llvm::yaml;
2060116d04dSCyndy Ishida using namespace llvm::MachO;
2070116d04dSCyndy Ishida 
2080116d04dSCyndy Ishida namespace {
2090116d04dSCyndy Ishida struct ExportSection {
2100116d04dSCyndy Ishida   std::vector<Architecture> Architectures;
2110116d04dSCyndy Ishida   std::vector<FlowStringRef> AllowableClients;
2120116d04dSCyndy Ishida   std::vector<FlowStringRef> ReexportedLibraries;
2130116d04dSCyndy Ishida   std::vector<FlowStringRef> Symbols;
2140116d04dSCyndy Ishida   std::vector<FlowStringRef> Classes;
2150116d04dSCyndy Ishida   std::vector<FlowStringRef> ClassEHs;
2160116d04dSCyndy Ishida   std::vector<FlowStringRef> IVars;
2170116d04dSCyndy Ishida   std::vector<FlowStringRef> WeakDefSymbols;
2180116d04dSCyndy Ishida   std::vector<FlowStringRef> TLVSymbols;
2190116d04dSCyndy Ishida };
2200116d04dSCyndy Ishida 
2210116d04dSCyndy Ishida struct UndefinedSection {
2220116d04dSCyndy Ishida   std::vector<Architecture> Architectures;
2230116d04dSCyndy Ishida   std::vector<FlowStringRef> Symbols;
2240116d04dSCyndy Ishida   std::vector<FlowStringRef> Classes;
2250116d04dSCyndy Ishida   std::vector<FlowStringRef> ClassEHs;
2260116d04dSCyndy Ishida   std::vector<FlowStringRef> IVars;
2270116d04dSCyndy Ishida   std::vector<FlowStringRef> WeakRefSymbols;
2280116d04dSCyndy Ishida };
2290116d04dSCyndy Ishida 
2300116d04dSCyndy Ishida // Sections for direct target mapping in TBDv4
2310116d04dSCyndy Ishida struct SymbolSection {
2320116d04dSCyndy Ishida   TargetList Targets;
2330116d04dSCyndy Ishida   std::vector<FlowStringRef> Symbols;
2340116d04dSCyndy Ishida   std::vector<FlowStringRef> Classes;
2350116d04dSCyndy Ishida   std::vector<FlowStringRef> ClassEHs;
2360116d04dSCyndy Ishida   std::vector<FlowStringRef> Ivars;
2370116d04dSCyndy Ishida   std::vector<FlowStringRef> WeakSymbols;
2380116d04dSCyndy Ishida   std::vector<FlowStringRef> TlvSymbols;
2390116d04dSCyndy Ishida };
2400116d04dSCyndy Ishida 
2410116d04dSCyndy Ishida struct MetadataSection {
2420116d04dSCyndy Ishida   enum Option { Clients, Libraries };
2430116d04dSCyndy Ishida   std::vector<Target> Targets;
2440116d04dSCyndy Ishida   std::vector<FlowStringRef> Values;
2450116d04dSCyndy Ishida };
2460116d04dSCyndy Ishida 
2470116d04dSCyndy Ishida struct UmbrellaSection {
2480116d04dSCyndy Ishida   std::vector<Target> Targets;
2490116d04dSCyndy Ishida   std::string Umbrella;
2500116d04dSCyndy Ishida };
2510116d04dSCyndy Ishida 
2520116d04dSCyndy Ishida // UUID's for TBDv4 are mapped to target not arch
2530116d04dSCyndy Ishida struct UUIDv4 {
2540116d04dSCyndy Ishida   Target TargetID;
2550116d04dSCyndy Ishida   std::string Value;
2560116d04dSCyndy Ishida 
2570116d04dSCyndy Ishida   UUIDv4() = default;
UUIDv4__anon8e5782510111::UUIDv42580116d04dSCyndy Ishida   UUIDv4(const Target &TargetID, const std::string &Value)
2590116d04dSCyndy Ishida       : TargetID(TargetID), Value(Value) {}
2600116d04dSCyndy Ishida };
2610116d04dSCyndy Ishida 
2620116d04dSCyndy Ishida // clang-format off
2630116d04dSCyndy Ishida enum TBDFlags : unsigned {
2640116d04dSCyndy Ishida   None                         = 0U,
2650116d04dSCyndy Ishida   FlatNamespace                = 1U << 0,
2660116d04dSCyndy Ishida   NotApplicationExtensionSafe  = 1U << 1,
2670116d04dSCyndy Ishida   InstallAPI                   = 1U << 2,
2680116d04dSCyndy Ishida   LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/InstallAPI),
2690116d04dSCyndy Ishida };
2700116d04dSCyndy Ishida // clang-format on
2710116d04dSCyndy Ishida } // end anonymous namespace.
2720116d04dSCyndy Ishida 
2730116d04dSCyndy Ishida LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(Architecture)
2740116d04dSCyndy Ishida LLVM_YAML_IS_SEQUENCE_VECTOR(ExportSection)
2750116d04dSCyndy Ishida LLVM_YAML_IS_SEQUENCE_VECTOR(UndefinedSection)
2760116d04dSCyndy Ishida // Specific to TBDv4
2770116d04dSCyndy Ishida LLVM_YAML_IS_SEQUENCE_VECTOR(SymbolSection)
2780116d04dSCyndy Ishida LLVM_YAML_IS_SEQUENCE_VECTOR(MetadataSection)
2790116d04dSCyndy Ishida LLVM_YAML_IS_SEQUENCE_VECTOR(UmbrellaSection)
2800116d04dSCyndy Ishida LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(Target)
2810116d04dSCyndy Ishida LLVM_YAML_IS_SEQUENCE_VECTOR(UUIDv4)
2820116d04dSCyndy Ishida 
2830116d04dSCyndy Ishida namespace llvm {
2840116d04dSCyndy Ishida namespace yaml {
2850116d04dSCyndy Ishida 
2860116d04dSCyndy Ishida template <> struct MappingTraits<ExportSection> {
mappingllvm::yaml::MappingTraits2870116d04dSCyndy Ishida   static void mapping(IO &IO, ExportSection &Section) {
2880116d04dSCyndy Ishida     const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
2890116d04dSCyndy Ishida     assert((!Ctx || (Ctx && Ctx->FileKind != FileType::Invalid)) &&
2900116d04dSCyndy Ishida            "File type is not set in YAML context");
2910116d04dSCyndy Ishida 
2920116d04dSCyndy Ishida     IO.mapRequired("archs", Section.Architectures);
2930116d04dSCyndy Ishida     if (Ctx->FileKind == FileType::TBD_V1)
2940116d04dSCyndy Ishida       IO.mapOptional("allowed-clients", Section.AllowableClients);
2950116d04dSCyndy Ishida     else
2960116d04dSCyndy Ishida       IO.mapOptional("allowable-clients", Section.AllowableClients);
2970116d04dSCyndy Ishida     IO.mapOptional("re-exports", Section.ReexportedLibraries);
2980116d04dSCyndy Ishida     IO.mapOptional("symbols", Section.Symbols);
2990116d04dSCyndy Ishida     IO.mapOptional("objc-classes", Section.Classes);
3000116d04dSCyndy Ishida     if (Ctx->FileKind == FileType::TBD_V3)
3010116d04dSCyndy Ishida       IO.mapOptional("objc-eh-types", Section.ClassEHs);
3020116d04dSCyndy Ishida     IO.mapOptional("objc-ivars", Section.IVars);
3030116d04dSCyndy Ishida     IO.mapOptional("weak-def-symbols", Section.WeakDefSymbols);
3040116d04dSCyndy Ishida     IO.mapOptional("thread-local-symbols", Section.TLVSymbols);
3050116d04dSCyndy Ishida   }
3060116d04dSCyndy Ishida };
3070116d04dSCyndy Ishida 
3080116d04dSCyndy Ishida template <> struct MappingTraits<UndefinedSection> {
mappingllvm::yaml::MappingTraits3090116d04dSCyndy Ishida   static void mapping(IO &IO, UndefinedSection &Section) {
3100116d04dSCyndy Ishida     const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
3110116d04dSCyndy Ishida     assert((!Ctx || (Ctx && Ctx->FileKind != FileType::Invalid)) &&
3120116d04dSCyndy Ishida            "File type is not set in YAML context");
3130116d04dSCyndy Ishida 
3140116d04dSCyndy Ishida     IO.mapRequired("archs", Section.Architectures);
3150116d04dSCyndy Ishida     IO.mapOptional("symbols", Section.Symbols);
3160116d04dSCyndy Ishida     IO.mapOptional("objc-classes", Section.Classes);
3170116d04dSCyndy Ishida     if (Ctx->FileKind == FileType::TBD_V3)
3180116d04dSCyndy Ishida       IO.mapOptional("objc-eh-types", Section.ClassEHs);
3190116d04dSCyndy Ishida     IO.mapOptional("objc-ivars", Section.IVars);
3200116d04dSCyndy Ishida     IO.mapOptional("weak-ref-symbols", Section.WeakRefSymbols);
3210116d04dSCyndy Ishida   }
3220116d04dSCyndy Ishida };
3230116d04dSCyndy Ishida 
3240116d04dSCyndy Ishida template <> struct MappingTraits<SymbolSection> {
mappingllvm::yaml::MappingTraits3250116d04dSCyndy Ishida   static void mapping(IO &IO, SymbolSection &Section) {
3260116d04dSCyndy Ishida     IO.mapRequired("targets", Section.Targets);
3270116d04dSCyndy Ishida     IO.mapOptional("symbols", Section.Symbols);
3280116d04dSCyndy Ishida     IO.mapOptional("objc-classes", Section.Classes);
3290116d04dSCyndy Ishida     IO.mapOptional("objc-eh-types", Section.ClassEHs);
3300116d04dSCyndy Ishida     IO.mapOptional("objc-ivars", Section.Ivars);
3310116d04dSCyndy Ishida     IO.mapOptional("weak-symbols", Section.WeakSymbols);
3320116d04dSCyndy Ishida     IO.mapOptional("thread-local-symbols", Section.TlvSymbols);
3330116d04dSCyndy Ishida   }
3340116d04dSCyndy Ishida };
3350116d04dSCyndy Ishida 
3360116d04dSCyndy Ishida template <> struct MappingTraits<UmbrellaSection> {
mappingllvm::yaml::MappingTraits3370116d04dSCyndy Ishida   static void mapping(IO &IO, UmbrellaSection &Section) {
3380116d04dSCyndy Ishida     IO.mapRequired("targets", Section.Targets);
3390116d04dSCyndy Ishida     IO.mapRequired("umbrella", Section.Umbrella);
3400116d04dSCyndy Ishida   }
3410116d04dSCyndy Ishida };
3420116d04dSCyndy Ishida 
3430116d04dSCyndy Ishida template <> struct MappingTraits<UUIDv4> {
mappingllvm::yaml::MappingTraits3440116d04dSCyndy Ishida   static void mapping(IO &IO, UUIDv4 &UUID) {
3450116d04dSCyndy Ishida     IO.mapRequired("target", UUID.TargetID);
3460116d04dSCyndy Ishida     IO.mapRequired("value", UUID.Value);
3470116d04dSCyndy Ishida   }
3480116d04dSCyndy Ishida };
3490116d04dSCyndy Ishida 
3500116d04dSCyndy Ishida template <>
3510116d04dSCyndy Ishida struct MappingContextTraits<MetadataSection, MetadataSection::Option> {
mappingllvm::yaml::MappingContextTraits3520116d04dSCyndy Ishida   static void mapping(IO &IO, MetadataSection &Section,
3530116d04dSCyndy Ishida                       MetadataSection::Option &OptionKind) {
3540116d04dSCyndy Ishida     IO.mapRequired("targets", Section.Targets);
3550116d04dSCyndy Ishida     switch (OptionKind) {
3560116d04dSCyndy Ishida     case MetadataSection::Option::Clients:
3570116d04dSCyndy Ishida       IO.mapRequired("clients", Section.Values);
3580116d04dSCyndy Ishida       return;
3590116d04dSCyndy Ishida     case MetadataSection::Option::Libraries:
3600116d04dSCyndy Ishida       IO.mapRequired("libraries", Section.Values);
3610116d04dSCyndy Ishida       return;
3620116d04dSCyndy Ishida     }
3630116d04dSCyndy Ishida     llvm_unreachable("unexpected option for metadata");
3640116d04dSCyndy Ishida   }
3650116d04dSCyndy Ishida };
3660116d04dSCyndy Ishida 
3670116d04dSCyndy Ishida template <> struct ScalarBitSetTraits<TBDFlags> {
bitsetllvm::yaml::ScalarBitSetTraits3680116d04dSCyndy Ishida   static void bitset(IO &IO, TBDFlags &Flags) {
3690116d04dSCyndy Ishida     IO.bitSetCase(Flags, "flat_namespace", TBDFlags::FlatNamespace);
3700116d04dSCyndy Ishida     IO.bitSetCase(Flags, "not_app_extension_safe",
3710116d04dSCyndy Ishida                   TBDFlags::NotApplicationExtensionSafe);
3720116d04dSCyndy Ishida     IO.bitSetCase(Flags, "installapi", TBDFlags::InstallAPI);
3730116d04dSCyndy Ishida   }
3740116d04dSCyndy Ishida };
3750116d04dSCyndy Ishida 
3760116d04dSCyndy Ishida template <> struct ScalarTraits<Target> {
outputllvm::yaml::ScalarTraits3770116d04dSCyndy Ishida   static void output(const Target &Value, void *, raw_ostream &OS) {
3780116d04dSCyndy Ishida     OS << Value.Arch << "-";
3790116d04dSCyndy Ishida     switch (Value.Platform) {
3800116d04dSCyndy Ishida     default:
3810116d04dSCyndy Ishida       OS << "unknown";
3820116d04dSCyndy Ishida       break;
383*3025c3edSJuergen Ributzka     case PLATFORM_MACOS:
3840116d04dSCyndy Ishida       OS << "macos";
3850116d04dSCyndy Ishida       break;
386*3025c3edSJuergen Ributzka     case PLATFORM_IOS:
3870116d04dSCyndy Ishida       OS << "ios";
3880116d04dSCyndy Ishida       break;
389*3025c3edSJuergen Ributzka     case PLATFORM_TVOS:
3900116d04dSCyndy Ishida       OS << "tvos";
3910116d04dSCyndy Ishida       break;
392*3025c3edSJuergen Ributzka     case PLATFORM_WATCHOS:
3930116d04dSCyndy Ishida       OS << "watchos";
3940116d04dSCyndy Ishida       break;
395*3025c3edSJuergen Ributzka     case PLATFORM_BRIDGEOS:
3960116d04dSCyndy Ishida       OS << "bridgeos";
3970116d04dSCyndy Ishida       break;
398*3025c3edSJuergen Ributzka     case PLATFORM_MACCATALYST:
3990116d04dSCyndy Ishida       OS << "maccatalyst";
4000116d04dSCyndy Ishida       break;
401*3025c3edSJuergen Ributzka     case PLATFORM_IOSSIMULATOR:
4020116d04dSCyndy Ishida       OS << "ios-simulator";
4030116d04dSCyndy Ishida       break;
404*3025c3edSJuergen Ributzka     case PLATFORM_TVOSSIMULATOR:
4050116d04dSCyndy Ishida       OS << "tvos-simulator";
4060116d04dSCyndy Ishida       break;
407*3025c3edSJuergen Ributzka     case PLATFORM_WATCHOSSIMULATOR:
4080116d04dSCyndy Ishida       OS << "watchos-simulator";
4090116d04dSCyndy Ishida       break;
410*3025c3edSJuergen Ributzka     case PLATFORM_DRIVERKIT:
4110116d04dSCyndy Ishida       OS << "driverkit";
4120116d04dSCyndy Ishida       break;
4130116d04dSCyndy Ishida     }
4140116d04dSCyndy Ishida   }
4150116d04dSCyndy Ishida 
inputllvm::yaml::ScalarTraits4160116d04dSCyndy Ishida   static StringRef input(StringRef Scalar, void *, Target &Value) {
4170116d04dSCyndy Ishida     auto Result = Target::create(Scalar);
4180116d04dSCyndy Ishida     if (!Result) {
4190116d04dSCyndy Ishida       consumeError(Result.takeError());
4200116d04dSCyndy Ishida       return "unparsable target";
4210116d04dSCyndy Ishida     }
4220116d04dSCyndy Ishida 
4230116d04dSCyndy Ishida     Value = *Result;
4240116d04dSCyndy Ishida     if (Value.Arch == AK_unknown)
4250116d04dSCyndy Ishida       return "unknown architecture";
426*3025c3edSJuergen Ributzka     if (Value.Platform == PLATFORM_UNKNOWN)
4270116d04dSCyndy Ishida       return "unknown platform";
4280116d04dSCyndy Ishida 
4290116d04dSCyndy Ishida     return {};
4300116d04dSCyndy Ishida   }
4310116d04dSCyndy Ishida 
mustQuotellvm::yaml::ScalarTraits4320116d04dSCyndy Ishida   static QuotingType mustQuote(StringRef) { return QuotingType::None; }
4330116d04dSCyndy Ishida };
4340116d04dSCyndy Ishida 
4350116d04dSCyndy Ishida template <> struct MappingTraits<const InterfaceFile *> {
4360116d04dSCyndy Ishida   struct NormalizedTBD {
NormalizedTBDllvm::yaml::MappingTraits::NormalizedTBD4370116d04dSCyndy Ishida     explicit NormalizedTBD(IO &IO) {}
NormalizedTBDllvm::yaml::MappingTraits::NormalizedTBD4380116d04dSCyndy Ishida     NormalizedTBD(IO &IO, const InterfaceFile *&File) {
4390116d04dSCyndy Ishida       Architectures = File->getArchitectures();
4400116d04dSCyndy Ishida       UUIDs = File->uuids();
4410116d04dSCyndy Ishida       Platforms = File->getPlatforms();
4420116d04dSCyndy Ishida       InstallName = File->getInstallName();
4430116d04dSCyndy Ishida       CurrentVersion = PackedVersion(File->getCurrentVersion());
4440116d04dSCyndy Ishida       CompatibilityVersion = PackedVersion(File->getCompatibilityVersion());
4450116d04dSCyndy Ishida       SwiftABIVersion = File->getSwiftABIVersion();
4460116d04dSCyndy Ishida       ObjCConstraint = File->getObjCConstraint();
4470116d04dSCyndy Ishida 
4480116d04dSCyndy Ishida       Flags = TBDFlags::None;
4490116d04dSCyndy Ishida       if (!File->isApplicationExtensionSafe())
4500116d04dSCyndy Ishida         Flags |= TBDFlags::NotApplicationExtensionSafe;
4510116d04dSCyndy Ishida 
4520116d04dSCyndy Ishida       if (!File->isTwoLevelNamespace())
4530116d04dSCyndy Ishida         Flags |= TBDFlags::FlatNamespace;
4540116d04dSCyndy Ishida 
4550116d04dSCyndy Ishida       if (File->isInstallAPI())
4560116d04dSCyndy Ishida         Flags |= TBDFlags::InstallAPI;
4570116d04dSCyndy Ishida 
4580116d04dSCyndy Ishida       if (!File->umbrellas().empty())
4590116d04dSCyndy Ishida         ParentUmbrella = File->umbrellas().begin()->second;
4600116d04dSCyndy Ishida 
4610116d04dSCyndy Ishida       std::set<ArchitectureSet> ArchSet;
4620116d04dSCyndy Ishida       for (const auto &Library : File->allowableClients())
4630116d04dSCyndy Ishida         ArchSet.insert(Library.getArchitectures());
4640116d04dSCyndy Ishida 
4650116d04dSCyndy Ishida       for (const auto &Library : File->reexportedLibraries())
4660116d04dSCyndy Ishida         ArchSet.insert(Library.getArchitectures());
4670116d04dSCyndy Ishida 
4680116d04dSCyndy Ishida       std::map<const Symbol *, ArchitectureSet> SymbolToArchSet;
4690116d04dSCyndy Ishida       for (const auto *Symbol : File->exports()) {
4700116d04dSCyndy Ishida         auto Architectures = Symbol->getArchitectures();
4710116d04dSCyndy Ishida         SymbolToArchSet[Symbol] = Architectures;
4720116d04dSCyndy Ishida         ArchSet.insert(Architectures);
4730116d04dSCyndy Ishida       }
4740116d04dSCyndy Ishida 
4750116d04dSCyndy Ishida       for (auto Architectures : ArchSet) {
4760116d04dSCyndy Ishida         ExportSection Section;
4770116d04dSCyndy Ishida         Section.Architectures = Architectures;
4780116d04dSCyndy Ishida 
4790116d04dSCyndy Ishida         for (const auto &Library : File->allowableClients())
4800116d04dSCyndy Ishida           if (Library.getArchitectures() == Architectures)
4810116d04dSCyndy Ishida             Section.AllowableClients.emplace_back(Library.getInstallName());
4820116d04dSCyndy Ishida 
4830116d04dSCyndy Ishida         for (const auto &Library : File->reexportedLibraries())
4840116d04dSCyndy Ishida           if (Library.getArchitectures() == Architectures)
4850116d04dSCyndy Ishida             Section.ReexportedLibraries.emplace_back(Library.getInstallName());
4860116d04dSCyndy Ishida 
4870116d04dSCyndy Ishida         for (const auto &SymArch : SymbolToArchSet) {
4880116d04dSCyndy Ishida           if (SymArch.second != Architectures)
4890116d04dSCyndy Ishida             continue;
4900116d04dSCyndy Ishida 
4910116d04dSCyndy Ishida           const auto *Symbol = SymArch.first;
4920116d04dSCyndy Ishida           switch (Symbol->getKind()) {
4930116d04dSCyndy Ishida           case SymbolKind::GlobalSymbol:
4940116d04dSCyndy Ishida             if (Symbol->isWeakDefined())
4950116d04dSCyndy Ishida               Section.WeakDefSymbols.emplace_back(Symbol->getName());
4960116d04dSCyndy Ishida             else if (Symbol->isThreadLocalValue())
4970116d04dSCyndy Ishida               Section.TLVSymbols.emplace_back(Symbol->getName());
4980116d04dSCyndy Ishida             else
4990116d04dSCyndy Ishida               Section.Symbols.emplace_back(Symbol->getName());
5000116d04dSCyndy Ishida             break;
5010116d04dSCyndy Ishida           case SymbolKind::ObjectiveCClass:
5020116d04dSCyndy Ishida             if (File->getFileType() != FileType::TBD_V3)
5030116d04dSCyndy Ishida               Section.Classes.emplace_back(
5040116d04dSCyndy Ishida                   copyString("_" + Symbol->getName().str()));
5050116d04dSCyndy Ishida             else
5060116d04dSCyndy Ishida               Section.Classes.emplace_back(Symbol->getName());
5070116d04dSCyndy Ishida             break;
5080116d04dSCyndy Ishida           case SymbolKind::ObjectiveCClassEHType:
5090116d04dSCyndy Ishida             if (File->getFileType() != FileType::TBD_V3)
5100116d04dSCyndy Ishida               Section.Symbols.emplace_back(
5110116d04dSCyndy Ishida                   copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str()));
5120116d04dSCyndy Ishida             else
5130116d04dSCyndy Ishida               Section.ClassEHs.emplace_back(Symbol->getName());
5140116d04dSCyndy Ishida             break;
5150116d04dSCyndy Ishida           case SymbolKind::ObjectiveCInstanceVariable:
5160116d04dSCyndy Ishida             if (File->getFileType() != FileType::TBD_V3)
5170116d04dSCyndy Ishida               Section.IVars.emplace_back(
5180116d04dSCyndy Ishida                   copyString("_" + Symbol->getName().str()));
5190116d04dSCyndy Ishida             else
5200116d04dSCyndy Ishida               Section.IVars.emplace_back(Symbol->getName());
5210116d04dSCyndy Ishida             break;
5220116d04dSCyndy Ishida           }
5230116d04dSCyndy Ishida         }
5240116d04dSCyndy Ishida         llvm::sort(Section.Symbols);
5250116d04dSCyndy Ishida         llvm::sort(Section.Classes);
5260116d04dSCyndy Ishida         llvm::sort(Section.ClassEHs);
5270116d04dSCyndy Ishida         llvm::sort(Section.IVars);
5280116d04dSCyndy Ishida         llvm::sort(Section.WeakDefSymbols);
5290116d04dSCyndy Ishida         llvm::sort(Section.TLVSymbols);
5300116d04dSCyndy Ishida         Exports.emplace_back(std::move(Section));
5310116d04dSCyndy Ishida       }
5320116d04dSCyndy Ishida 
5330116d04dSCyndy Ishida       ArchSet.clear();
5340116d04dSCyndy Ishida       SymbolToArchSet.clear();
5350116d04dSCyndy Ishida 
5360116d04dSCyndy Ishida       for (const auto *Symbol : File->undefineds()) {
5370116d04dSCyndy Ishida         auto Architectures = Symbol->getArchitectures();
5380116d04dSCyndy Ishida         SymbolToArchSet[Symbol] = Architectures;
5390116d04dSCyndy Ishida         ArchSet.insert(Architectures);
5400116d04dSCyndy Ishida       }
5410116d04dSCyndy Ishida 
5420116d04dSCyndy Ishida       for (auto Architectures : ArchSet) {
5430116d04dSCyndy Ishida         UndefinedSection Section;
5440116d04dSCyndy Ishida         Section.Architectures = Architectures;
5450116d04dSCyndy Ishida 
5460116d04dSCyndy Ishida         for (const auto &SymArch : SymbolToArchSet) {
5470116d04dSCyndy Ishida           if (SymArch.second != Architectures)
5480116d04dSCyndy Ishida             continue;
5490116d04dSCyndy Ishida 
5500116d04dSCyndy Ishida           const auto *Symbol = SymArch.first;
5510116d04dSCyndy Ishida           switch (Symbol->getKind()) {
5520116d04dSCyndy Ishida           case SymbolKind::GlobalSymbol:
5530116d04dSCyndy Ishida             if (Symbol->isWeakReferenced())
5540116d04dSCyndy Ishida               Section.WeakRefSymbols.emplace_back(Symbol->getName());
5550116d04dSCyndy Ishida             else
5560116d04dSCyndy Ishida               Section.Symbols.emplace_back(Symbol->getName());
5570116d04dSCyndy Ishida             break;
5580116d04dSCyndy Ishida           case SymbolKind::ObjectiveCClass:
5590116d04dSCyndy Ishida             if (File->getFileType() != FileType::TBD_V3)
5600116d04dSCyndy Ishida               Section.Classes.emplace_back(
5610116d04dSCyndy Ishida                   copyString("_" + Symbol->getName().str()));
5620116d04dSCyndy Ishida             else
5630116d04dSCyndy Ishida               Section.Classes.emplace_back(Symbol->getName());
5640116d04dSCyndy Ishida             break;
5650116d04dSCyndy Ishida           case SymbolKind::ObjectiveCClassEHType:
5660116d04dSCyndy Ishida             if (File->getFileType() != FileType::TBD_V3)
5670116d04dSCyndy Ishida               Section.Symbols.emplace_back(
5680116d04dSCyndy Ishida                   copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str()));
5690116d04dSCyndy Ishida             else
5700116d04dSCyndy Ishida               Section.ClassEHs.emplace_back(Symbol->getName());
5710116d04dSCyndy Ishida             break;
5720116d04dSCyndy Ishida           case SymbolKind::ObjectiveCInstanceVariable:
5730116d04dSCyndy Ishida             if (File->getFileType() != FileType::TBD_V3)
5740116d04dSCyndy Ishida               Section.IVars.emplace_back(
5750116d04dSCyndy Ishida                   copyString("_" + Symbol->getName().str()));
5760116d04dSCyndy Ishida             else
5770116d04dSCyndy Ishida               Section.IVars.emplace_back(Symbol->getName());
5780116d04dSCyndy Ishida             break;
5790116d04dSCyndy Ishida           }
5800116d04dSCyndy Ishida         }
5810116d04dSCyndy Ishida         llvm::sort(Section.Symbols);
5820116d04dSCyndy Ishida         llvm::sort(Section.Classes);
5830116d04dSCyndy Ishida         llvm::sort(Section.ClassEHs);
5840116d04dSCyndy Ishida         llvm::sort(Section.IVars);
5850116d04dSCyndy Ishida         llvm::sort(Section.WeakRefSymbols);
5860116d04dSCyndy Ishida         Undefineds.emplace_back(std::move(Section));
5870116d04dSCyndy Ishida       }
5880116d04dSCyndy Ishida     }
5890116d04dSCyndy Ishida 
5900116d04dSCyndy Ishida     // TBD v1 - TBD v3 files only support one platform and several
5910116d04dSCyndy Ishida     // architectures. It is possible to have more than one platform for TBD v3
5920116d04dSCyndy Ishida     // files, but the architectures don't apply to all
5930116d04dSCyndy Ishida     // platforms, specifically to filter out the i386 slice from
5940116d04dSCyndy Ishida     // platform macCatalyst.
synthesizeTargetsllvm::yaml::MappingTraits::NormalizedTBD5950116d04dSCyndy Ishida     TargetList synthesizeTargets(ArchitectureSet Architectures,
5960116d04dSCyndy Ishida                                  const PlatformSet &Platforms) {
5970116d04dSCyndy Ishida       TargetList Targets;
5980116d04dSCyndy Ishida 
5990116d04dSCyndy Ishida       for (auto Platform : Platforms) {
600*3025c3edSJuergen Ributzka         Platform = mapToPlatformType(Platform, Architectures.hasX86());
6010116d04dSCyndy Ishida 
6020116d04dSCyndy Ishida         for (const auto &&Architecture : Architectures) {
603*3025c3edSJuergen Ributzka           if ((Architecture == AK_i386) && (Platform == PLATFORM_MACCATALYST))
6040116d04dSCyndy Ishida             continue;
6050116d04dSCyndy Ishida 
6060116d04dSCyndy Ishida           Targets.emplace_back(Architecture, Platform);
6070116d04dSCyndy Ishida         }
6080116d04dSCyndy Ishida       }
6090116d04dSCyndy Ishida       return Targets;
6100116d04dSCyndy Ishida     }
6110116d04dSCyndy Ishida 
denormalizellvm::yaml::MappingTraits::NormalizedTBD6120116d04dSCyndy Ishida     const InterfaceFile *denormalize(IO &IO) {
6130116d04dSCyndy Ishida       auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
6140116d04dSCyndy Ishida       assert(Ctx);
6150116d04dSCyndy Ishida 
6160116d04dSCyndy Ishida       auto *File = new InterfaceFile;
6170116d04dSCyndy Ishida       File->setPath(Ctx->Path);
6180116d04dSCyndy Ishida       File->setFileType(Ctx->FileKind);
6190116d04dSCyndy Ishida       File->addTargets(synthesizeTargets(Architectures, Platforms));
6200116d04dSCyndy Ishida       for (auto &ID : UUIDs)
6210116d04dSCyndy Ishida         File->addUUID(ID.first, ID.second);
6220116d04dSCyndy Ishida       File->setInstallName(InstallName);
6230116d04dSCyndy Ishida       File->setCurrentVersion(CurrentVersion);
6240116d04dSCyndy Ishida       File->setCompatibilityVersion(CompatibilityVersion);
6250116d04dSCyndy Ishida       File->setSwiftABIVersion(SwiftABIVersion);
6260116d04dSCyndy Ishida       File->setObjCConstraint(ObjCConstraint);
6270116d04dSCyndy Ishida       for (const auto &Target : File->targets())
6280116d04dSCyndy Ishida         File->addParentUmbrella(Target, ParentUmbrella);
6290116d04dSCyndy Ishida 
6300116d04dSCyndy Ishida       if (Ctx->FileKind == FileType::TBD_V1) {
6310116d04dSCyndy Ishida         File->setTwoLevelNamespace();
6320116d04dSCyndy Ishida         File->setApplicationExtensionSafe();
6330116d04dSCyndy Ishida       } else {
6340116d04dSCyndy Ishida         File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
6350116d04dSCyndy Ishida         File->setApplicationExtensionSafe(
6360116d04dSCyndy Ishida             !(Flags & TBDFlags::NotApplicationExtensionSafe));
6370116d04dSCyndy Ishida         File->setInstallAPI(Flags & TBDFlags::InstallAPI);
6380116d04dSCyndy Ishida       }
6390116d04dSCyndy Ishida 
6400116d04dSCyndy Ishida       for (const auto &Section : Exports) {
6410116d04dSCyndy Ishida         const auto Targets =
6420116d04dSCyndy Ishida             synthesizeTargets(Section.Architectures, Platforms);
6430116d04dSCyndy Ishida 
6440116d04dSCyndy Ishida         for (const auto &Lib : Section.AllowableClients)
6450116d04dSCyndy Ishida           for (const auto &Target : Targets)
6460116d04dSCyndy Ishida             File->addAllowableClient(Lib, Target);
6470116d04dSCyndy Ishida 
6480116d04dSCyndy Ishida         for (const auto &Lib : Section.ReexportedLibraries)
6490116d04dSCyndy Ishida           for (const auto &Target : Targets)
6500116d04dSCyndy Ishida             File->addReexportedLibrary(Lib, Target);
6510116d04dSCyndy Ishida 
6520116d04dSCyndy Ishida         for (const auto &Symbol : Section.Symbols) {
6530116d04dSCyndy Ishida           if (Ctx->FileKind != FileType::TBD_V3 &&
6540116d04dSCyndy Ishida               Symbol.value.startswith("_OBJC_EHTYPE_$_"))
6550116d04dSCyndy Ishida             File->addSymbol(SymbolKind::ObjectiveCClassEHType,
6560116d04dSCyndy Ishida                             Symbol.value.drop_front(15), Targets);
6570116d04dSCyndy Ishida           else
6580116d04dSCyndy Ishida             File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets);
6590116d04dSCyndy Ishida         }
6600116d04dSCyndy Ishida         for (auto &Symbol : Section.Classes) {
6610116d04dSCyndy Ishida           auto Name = Symbol.value;
6620116d04dSCyndy Ishida           if (Ctx->FileKind != FileType::TBD_V3)
6630116d04dSCyndy Ishida             Name = Name.drop_front();
6640116d04dSCyndy Ishida           File->addSymbol(SymbolKind::ObjectiveCClass, Name, Targets);
6650116d04dSCyndy Ishida         }
6660116d04dSCyndy Ishida         for (auto &Symbol : Section.ClassEHs)
6670116d04dSCyndy Ishida           File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol, Targets);
6680116d04dSCyndy Ishida         for (auto &Symbol : Section.IVars) {
6690116d04dSCyndy Ishida           auto Name = Symbol.value;
6700116d04dSCyndy Ishida           if (Ctx->FileKind != FileType::TBD_V3)
6710116d04dSCyndy Ishida             Name = Name.drop_front();
6720116d04dSCyndy Ishida           File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name,
6730116d04dSCyndy Ishida                           Targets);
6740116d04dSCyndy Ishida         }
6750116d04dSCyndy Ishida         for (auto &Symbol : Section.WeakDefSymbols)
6760116d04dSCyndy Ishida           File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
6770116d04dSCyndy Ishida                           SymbolFlags::WeakDefined);
6780116d04dSCyndy Ishida         for (auto &Symbol : Section.TLVSymbols)
6790116d04dSCyndy Ishida           File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
6800116d04dSCyndy Ishida                           SymbolFlags::ThreadLocalValue);
6810116d04dSCyndy Ishida       }
6820116d04dSCyndy Ishida 
6830116d04dSCyndy Ishida       for (const auto &Section : Undefineds) {
6840116d04dSCyndy Ishida         const auto Targets =
6850116d04dSCyndy Ishida             synthesizeTargets(Section.Architectures, Platforms);
6860116d04dSCyndy Ishida         for (auto &Symbol : Section.Symbols) {
6870116d04dSCyndy Ishida           if (Ctx->FileKind != FileType::TBD_V3 &&
6880116d04dSCyndy Ishida               Symbol.value.startswith("_OBJC_EHTYPE_$_"))
6890116d04dSCyndy Ishida             File->addSymbol(SymbolKind::ObjectiveCClassEHType,
6900116d04dSCyndy Ishida                             Symbol.value.drop_front(15), Targets,
6910116d04dSCyndy Ishida                             SymbolFlags::Undefined);
6920116d04dSCyndy Ishida           else
6930116d04dSCyndy Ishida             File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
6940116d04dSCyndy Ishida                             SymbolFlags::Undefined);
6950116d04dSCyndy Ishida         }
6960116d04dSCyndy Ishida         for (auto &Symbol : Section.Classes) {
6970116d04dSCyndy Ishida           auto Name = Symbol.value;
6980116d04dSCyndy Ishida           if (Ctx->FileKind != FileType::TBD_V3)
6990116d04dSCyndy Ishida             Name = Name.drop_front();
7000116d04dSCyndy Ishida           File->addSymbol(SymbolKind::ObjectiveCClass, Name, Targets,
7010116d04dSCyndy Ishida                           SymbolFlags::Undefined);
7020116d04dSCyndy Ishida         }
7030116d04dSCyndy Ishida         for (auto &Symbol : Section.ClassEHs)
7040116d04dSCyndy Ishida           File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol, Targets,
7050116d04dSCyndy Ishida                           SymbolFlags::Undefined);
7060116d04dSCyndy Ishida         for (auto &Symbol : Section.IVars) {
7070116d04dSCyndy Ishida           auto Name = Symbol.value;
7080116d04dSCyndy Ishida           if (Ctx->FileKind != FileType::TBD_V3)
7090116d04dSCyndy Ishida             Name = Name.drop_front();
7100116d04dSCyndy Ishida           File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name, Targets,
7110116d04dSCyndy Ishida                           SymbolFlags::Undefined);
7120116d04dSCyndy Ishida         }
7130116d04dSCyndy Ishida         for (auto &Symbol : Section.WeakRefSymbols)
7140116d04dSCyndy Ishida           File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets,
7150116d04dSCyndy Ishida                           SymbolFlags::Undefined | SymbolFlags::WeakReferenced);
7160116d04dSCyndy Ishida       }
7170116d04dSCyndy Ishida 
7180116d04dSCyndy Ishida       return File;
7190116d04dSCyndy Ishida     }
7200116d04dSCyndy Ishida 
7210116d04dSCyndy Ishida     llvm::BumpPtrAllocator Allocator;
copyStringllvm::yaml::MappingTraits::NormalizedTBD7220116d04dSCyndy Ishida     StringRef copyString(StringRef String) {
7230116d04dSCyndy Ishida       if (String.empty())
7240116d04dSCyndy Ishida         return {};
7250116d04dSCyndy Ishida 
7260116d04dSCyndy Ishida       void *Ptr = Allocator.Allocate(String.size(), 1);
7270116d04dSCyndy Ishida       memcpy(Ptr, String.data(), String.size());
7280116d04dSCyndy Ishida       return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
7290116d04dSCyndy Ishida     }
7300116d04dSCyndy Ishida 
7310116d04dSCyndy Ishida     std::vector<Architecture> Architectures;
7320116d04dSCyndy Ishida     std::vector<UUID> UUIDs;
7330116d04dSCyndy Ishida     PlatformSet Platforms;
7340116d04dSCyndy Ishida     StringRef InstallName;
7350116d04dSCyndy Ishida     PackedVersion CurrentVersion;
7360116d04dSCyndy Ishida     PackedVersion CompatibilityVersion;
7370116d04dSCyndy Ishida     SwiftVersion SwiftABIVersion{0};
7380116d04dSCyndy Ishida     ObjCConstraintType ObjCConstraint{ObjCConstraintType::None};
7390116d04dSCyndy Ishida     TBDFlags Flags{TBDFlags::None};
7400116d04dSCyndy Ishida     StringRef ParentUmbrella;
7410116d04dSCyndy Ishida     std::vector<ExportSection> Exports;
7420116d04dSCyndy Ishida     std::vector<UndefinedSection> Undefineds;
7430116d04dSCyndy Ishida   };
7440116d04dSCyndy Ishida 
setFileTypeForInputllvm::yaml::MappingTraits7450116d04dSCyndy Ishida   static void setFileTypeForInput(TextAPIContext *Ctx, IO &IO) {
7460116d04dSCyndy Ishida     if (IO.mapTag("!tapi-tbd", false))
7470116d04dSCyndy Ishida       Ctx->FileKind = FileType::TBD_V4;
7480116d04dSCyndy Ishida     else if (IO.mapTag("!tapi-tbd-v3", false))
7490116d04dSCyndy Ishida       Ctx->FileKind = FileType::TBD_V3;
7500116d04dSCyndy Ishida     else if (IO.mapTag("!tapi-tbd-v2", false))
7510116d04dSCyndy Ishida       Ctx->FileKind = FileType::TBD_V2;
7520116d04dSCyndy Ishida     else if (IO.mapTag("!tapi-tbd-v1", false) ||
7530116d04dSCyndy Ishida              IO.mapTag("tag:yaml.org,2002:map", false))
7540116d04dSCyndy Ishida       Ctx->FileKind = FileType::TBD_V1;
7550116d04dSCyndy Ishida     else {
7560116d04dSCyndy Ishida       Ctx->FileKind = FileType::Invalid;
7570116d04dSCyndy Ishida       return;
7580116d04dSCyndy Ishida     }
7590116d04dSCyndy Ishida   }
7600116d04dSCyndy Ishida 
mappingllvm::yaml::MappingTraits7610116d04dSCyndy Ishida   static void mapping(IO &IO, const InterfaceFile *&File) {
7620116d04dSCyndy Ishida     auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
7630116d04dSCyndy Ishida     assert((!Ctx || !IO.outputting() ||
7640116d04dSCyndy Ishida             (Ctx && Ctx->FileKind != FileType::Invalid)) &&
7650116d04dSCyndy Ishida            "File type is not set in YAML context");
7660116d04dSCyndy Ishida 
7670116d04dSCyndy Ishida     if (!IO.outputting()) {
7680116d04dSCyndy Ishida       setFileTypeForInput(Ctx, IO);
7690116d04dSCyndy Ishida       switch (Ctx->FileKind) {
7700116d04dSCyndy Ishida       default:
7710116d04dSCyndy Ishida         break;
7720116d04dSCyndy Ishida       case FileType::TBD_V4:
7730116d04dSCyndy Ishida         mapKeysToValuesV4(IO, File);
7740116d04dSCyndy Ishida         return;
7750116d04dSCyndy Ishida       case FileType::Invalid:
7760116d04dSCyndy Ishida         IO.setError("unsupported file type");
7770116d04dSCyndy Ishida         return;
7780116d04dSCyndy Ishida       }
7790116d04dSCyndy Ishida     } else {
7800116d04dSCyndy Ishida       // Set file type when writing.
7810116d04dSCyndy Ishida       switch (Ctx->FileKind) {
7820116d04dSCyndy Ishida       default:
7830116d04dSCyndy Ishida         llvm_unreachable("unexpected file type");
7840116d04dSCyndy Ishida       case FileType::TBD_V4:
7850116d04dSCyndy Ishida         mapKeysToValuesV4(IO, File);
7860116d04dSCyndy Ishida         return;
7870116d04dSCyndy Ishida       case FileType::TBD_V3:
7880116d04dSCyndy Ishida         IO.mapTag("!tapi-tbd-v3", true);
7890116d04dSCyndy Ishida         break;
7900116d04dSCyndy Ishida       case FileType::TBD_V2:
7910116d04dSCyndy Ishida         IO.mapTag("!tapi-tbd-v2", true);
7920116d04dSCyndy Ishida         break;
7930116d04dSCyndy Ishida       case FileType::TBD_V1:
7940116d04dSCyndy Ishida         // Don't write the tag into the .tbd file for TBD v1
7950116d04dSCyndy Ishida         break;
7960116d04dSCyndy Ishida       }
7970116d04dSCyndy Ishida     }
7980116d04dSCyndy Ishida     mapKeysToValues(Ctx->FileKind, IO, File);
7990116d04dSCyndy Ishida   }
8000116d04dSCyndy Ishida 
8010116d04dSCyndy Ishida   using SectionList = std::vector<SymbolSection>;
8020116d04dSCyndy Ishida   struct NormalizedTBD_V4 {
NormalizedTBD_V4llvm::yaml::MappingTraits::NormalizedTBD_V48030116d04dSCyndy Ishida     explicit NormalizedTBD_V4(IO &IO) {}
NormalizedTBD_V4llvm::yaml::MappingTraits::NormalizedTBD_V48040116d04dSCyndy Ishida     NormalizedTBD_V4(IO &IO, const InterfaceFile *&File) {
8050116d04dSCyndy Ishida       auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
8060116d04dSCyndy Ishida       assert(Ctx);
8070116d04dSCyndy Ishida       TBDVersion = Ctx->FileKind >> 1;
8080116d04dSCyndy Ishida       Targets.insert(Targets.begin(), File->targets().begin(),
8090116d04dSCyndy Ishida                      File->targets().end());
8100116d04dSCyndy Ishida       for (const auto &IT : File->uuids())
8110116d04dSCyndy Ishida         UUIDs.emplace_back(IT.first, IT.second);
8120116d04dSCyndy Ishida       InstallName = File->getInstallName();
8130116d04dSCyndy Ishida       CurrentVersion = File->getCurrentVersion();
8140116d04dSCyndy Ishida       CompatibilityVersion = File->getCompatibilityVersion();
8150116d04dSCyndy Ishida       SwiftABIVersion = File->getSwiftABIVersion();
8160116d04dSCyndy Ishida 
8170116d04dSCyndy Ishida       Flags = TBDFlags::None;
8180116d04dSCyndy Ishida       if (!File->isApplicationExtensionSafe())
8190116d04dSCyndy Ishida         Flags |= TBDFlags::NotApplicationExtensionSafe;
8200116d04dSCyndy Ishida 
8210116d04dSCyndy Ishida       if (!File->isTwoLevelNamespace())
8220116d04dSCyndy Ishida         Flags |= TBDFlags::FlatNamespace;
8230116d04dSCyndy Ishida 
8240116d04dSCyndy Ishida       if (File->isInstallAPI())
8250116d04dSCyndy Ishida         Flags |= TBDFlags::InstallAPI;
8260116d04dSCyndy Ishida 
8270116d04dSCyndy Ishida       {
8280116d04dSCyndy Ishida         std::map<std::string, TargetList> valueToTargetList;
8290116d04dSCyndy Ishida         for (const auto &it : File->umbrellas())
8300116d04dSCyndy Ishida           valueToTargetList[it.second].emplace_back(it.first);
8310116d04dSCyndy Ishida 
8320116d04dSCyndy Ishida         for (const auto &it : valueToTargetList) {
8330116d04dSCyndy Ishida           UmbrellaSection CurrentSection;
8340116d04dSCyndy Ishida           CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
8350116d04dSCyndy Ishida                                         it.second.begin(), it.second.end());
8360116d04dSCyndy Ishida           CurrentSection.Umbrella = it.first;
8370116d04dSCyndy Ishida           ParentUmbrellas.emplace_back(std::move(CurrentSection));
8380116d04dSCyndy Ishida         }
8390116d04dSCyndy Ishida       }
8400116d04dSCyndy Ishida 
8410116d04dSCyndy Ishida       assignTargetsToLibrary(File->allowableClients(), AllowableClients);
8420116d04dSCyndy Ishida       assignTargetsToLibrary(File->reexportedLibraries(), ReexportedLibraries);
8430116d04dSCyndy Ishida 
8440116d04dSCyndy Ishida       auto handleSymbols =
8450116d04dSCyndy Ishida           [](SectionList &CurrentSections,
8460116d04dSCyndy Ishida              InterfaceFile::const_filtered_symbol_range Symbols,
8470116d04dSCyndy Ishida              std::function<bool(const Symbol *)> Pred) {
8480116d04dSCyndy Ishida             std::set<TargetList> TargetSet;
8490116d04dSCyndy Ishida             std::map<const Symbol *, TargetList> SymbolToTargetList;
8500116d04dSCyndy Ishida             for (const auto *Symbol : Symbols) {
8510116d04dSCyndy Ishida               if (!Pred(Symbol))
8520116d04dSCyndy Ishida                 continue;
8530116d04dSCyndy Ishida               TargetList Targets(Symbol->targets());
8540116d04dSCyndy Ishida               SymbolToTargetList[Symbol] = Targets;
8550116d04dSCyndy Ishida               TargetSet.emplace(std::move(Targets));
8560116d04dSCyndy Ishida             }
8570116d04dSCyndy Ishida             for (const auto &TargetIDs : TargetSet) {
8580116d04dSCyndy Ishida               SymbolSection CurrentSection;
8590116d04dSCyndy Ishida               CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
8600116d04dSCyndy Ishida                                             TargetIDs.begin(), TargetIDs.end());
8610116d04dSCyndy Ishida 
8620116d04dSCyndy Ishida               for (const auto &IT : SymbolToTargetList) {
8630116d04dSCyndy Ishida                 if (IT.second != TargetIDs)
8640116d04dSCyndy Ishida                   continue;
8650116d04dSCyndy Ishida 
8660116d04dSCyndy Ishida                 const auto *Symbol = IT.first;
8670116d04dSCyndy Ishida                 switch (Symbol->getKind()) {
8680116d04dSCyndy Ishida                 case SymbolKind::GlobalSymbol:
8690116d04dSCyndy Ishida                   if (Symbol->isWeakDefined())
8700116d04dSCyndy Ishida                     CurrentSection.WeakSymbols.emplace_back(Symbol->getName());
8710116d04dSCyndy Ishida                   else if (Symbol->isThreadLocalValue())
8720116d04dSCyndy Ishida                     CurrentSection.TlvSymbols.emplace_back(Symbol->getName());
8730116d04dSCyndy Ishida                   else
8740116d04dSCyndy Ishida                     CurrentSection.Symbols.emplace_back(Symbol->getName());
8750116d04dSCyndy Ishida                   break;
8760116d04dSCyndy Ishida                 case SymbolKind::ObjectiveCClass:
8770116d04dSCyndy Ishida                   CurrentSection.Classes.emplace_back(Symbol->getName());
8780116d04dSCyndy Ishida                   break;
8790116d04dSCyndy Ishida                 case SymbolKind::ObjectiveCClassEHType:
8800116d04dSCyndy Ishida                   CurrentSection.ClassEHs.emplace_back(Symbol->getName());
8810116d04dSCyndy Ishida                   break;
8820116d04dSCyndy Ishida                 case SymbolKind::ObjectiveCInstanceVariable:
8830116d04dSCyndy Ishida                   CurrentSection.Ivars.emplace_back(Symbol->getName());
8840116d04dSCyndy Ishida                   break;
8850116d04dSCyndy Ishida                 }
8860116d04dSCyndy Ishida               }
8870116d04dSCyndy Ishida               sort(CurrentSection.Symbols);
8880116d04dSCyndy Ishida               sort(CurrentSection.Classes);
8890116d04dSCyndy Ishida               sort(CurrentSection.ClassEHs);
8900116d04dSCyndy Ishida               sort(CurrentSection.Ivars);
8910116d04dSCyndy Ishida               sort(CurrentSection.WeakSymbols);
8920116d04dSCyndy Ishida               sort(CurrentSection.TlvSymbols);
8930116d04dSCyndy Ishida               CurrentSections.emplace_back(std::move(CurrentSection));
8940116d04dSCyndy Ishida             }
8950116d04dSCyndy Ishida           };
8960116d04dSCyndy Ishida 
8970116d04dSCyndy Ishida       handleSymbols(Exports, File->exports(), [](const Symbol *Symbol) {
8980116d04dSCyndy Ishida         return !Symbol->isReexported();
8990116d04dSCyndy Ishida       });
9000116d04dSCyndy Ishida       handleSymbols(Reexports, File->exports(), [](const Symbol *Symbol) {
9010116d04dSCyndy Ishida         return Symbol->isReexported();
9020116d04dSCyndy Ishida       });
9030116d04dSCyndy Ishida       handleSymbols(Undefineds, File->undefineds(),
9040116d04dSCyndy Ishida                     [](const Symbol *Symbol) { return true; });
9050116d04dSCyndy Ishida     }
9060116d04dSCyndy Ishida 
denormalizellvm::yaml::MappingTraits::NormalizedTBD_V49070116d04dSCyndy Ishida     const InterfaceFile *denormalize(IO &IO) {
9080116d04dSCyndy Ishida       auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
9090116d04dSCyndy Ishida       assert(Ctx);
9100116d04dSCyndy Ishida 
9110116d04dSCyndy Ishida       auto *File = new InterfaceFile;
9120116d04dSCyndy Ishida       File->setPath(Ctx->Path);
9130116d04dSCyndy Ishida       File->setFileType(Ctx->FileKind);
9140116d04dSCyndy Ishida       for (auto &id : UUIDs)
9150116d04dSCyndy Ishida         File->addUUID(id.TargetID, id.Value);
9160116d04dSCyndy Ishida       File->addTargets(Targets);
9170116d04dSCyndy Ishida       File->setInstallName(InstallName);
9180116d04dSCyndy Ishida       File->setCurrentVersion(CurrentVersion);
9190116d04dSCyndy Ishida       File->setCompatibilityVersion(CompatibilityVersion);
9200116d04dSCyndy Ishida       File->setSwiftABIVersion(SwiftABIVersion);
9210116d04dSCyndy Ishida       for (const auto &CurrentSection : ParentUmbrellas)
9220116d04dSCyndy Ishida         for (const auto &target : CurrentSection.Targets)
9230116d04dSCyndy Ishida           File->addParentUmbrella(target, CurrentSection.Umbrella);
9240116d04dSCyndy Ishida       File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
9250116d04dSCyndy Ishida       File->setApplicationExtensionSafe(
9260116d04dSCyndy Ishida           !(Flags & TBDFlags::NotApplicationExtensionSafe));
9270116d04dSCyndy Ishida       File->setInstallAPI(Flags & TBDFlags::InstallAPI);
9280116d04dSCyndy Ishida 
9290116d04dSCyndy Ishida       for (const auto &CurrentSection : AllowableClients) {
9300116d04dSCyndy Ishida         for (const auto &lib : CurrentSection.Values)
9310116d04dSCyndy Ishida           for (const auto &Target : CurrentSection.Targets)
9320116d04dSCyndy Ishida             File->addAllowableClient(lib, Target);
9330116d04dSCyndy Ishida       }
9340116d04dSCyndy Ishida 
9350116d04dSCyndy Ishida       for (const auto &CurrentSection : ReexportedLibraries) {
9360116d04dSCyndy Ishida         for (const auto &Lib : CurrentSection.Values)
9370116d04dSCyndy Ishida           for (const auto &Target : CurrentSection.Targets)
9380116d04dSCyndy Ishida             File->addReexportedLibrary(Lib, Target);
9390116d04dSCyndy Ishida       }
9400116d04dSCyndy Ishida 
9410116d04dSCyndy Ishida       auto handleSymbols = [File](const SectionList &CurrentSections,
9420116d04dSCyndy Ishida                                   SymbolFlags Flag = SymbolFlags::None) {
9430116d04dSCyndy Ishida         for (const auto &CurrentSection : CurrentSections) {
9440116d04dSCyndy Ishida           for (auto &sym : CurrentSection.Symbols)
9450116d04dSCyndy Ishida             File->addSymbol(SymbolKind::GlobalSymbol, sym,
9460116d04dSCyndy Ishida                             CurrentSection.Targets, Flag);
9470116d04dSCyndy Ishida 
9480116d04dSCyndy Ishida           for (auto &sym : CurrentSection.Classes)
9490116d04dSCyndy Ishida             File->addSymbol(SymbolKind::ObjectiveCClass, sym,
9500116d04dSCyndy Ishida                             CurrentSection.Targets);
9510116d04dSCyndy Ishida 
9520116d04dSCyndy Ishida           for (auto &sym : CurrentSection.ClassEHs)
9530116d04dSCyndy Ishida             File->addSymbol(SymbolKind::ObjectiveCClassEHType, sym,
9540116d04dSCyndy Ishida                             CurrentSection.Targets);
9550116d04dSCyndy Ishida 
9560116d04dSCyndy Ishida           for (auto &sym : CurrentSection.Ivars)
9570116d04dSCyndy Ishida             File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, sym,
9580116d04dSCyndy Ishida                             CurrentSection.Targets);
9590116d04dSCyndy Ishida 
9600116d04dSCyndy Ishida           for (auto &sym : CurrentSection.WeakSymbols)
9610116d04dSCyndy Ishida             File->addSymbol(SymbolKind::GlobalSymbol, sym,
9620116d04dSCyndy Ishida                             CurrentSection.Targets, SymbolFlags::WeakDefined);
9630116d04dSCyndy Ishida 
9640116d04dSCyndy Ishida           for (auto &sym : CurrentSection.TlvSymbols)
9650116d04dSCyndy Ishida             File->addSymbol(SymbolKind::GlobalSymbol, sym,
9660116d04dSCyndy Ishida                             CurrentSection.Targets,
9670116d04dSCyndy Ishida                             SymbolFlags::ThreadLocalValue);
9680116d04dSCyndy Ishida         }
9690116d04dSCyndy Ishida       };
9700116d04dSCyndy Ishida 
9710116d04dSCyndy Ishida       handleSymbols(Exports);
9720116d04dSCyndy Ishida       handleSymbols(Reexports, SymbolFlags::Rexported);
9730116d04dSCyndy Ishida       handleSymbols(Undefineds, SymbolFlags::Undefined);
9740116d04dSCyndy Ishida 
9750116d04dSCyndy Ishida       return File;
9760116d04dSCyndy Ishida     }
9770116d04dSCyndy Ishida 
9780116d04dSCyndy Ishida     unsigned TBDVersion;
9790116d04dSCyndy Ishida     std::vector<UUIDv4> UUIDs;
9800116d04dSCyndy Ishida     TargetList Targets;
9810116d04dSCyndy Ishida     StringRef InstallName;
9820116d04dSCyndy Ishida     PackedVersion CurrentVersion;
9830116d04dSCyndy Ishida     PackedVersion CompatibilityVersion;
9840116d04dSCyndy Ishida     SwiftVersion SwiftABIVersion{0};
9850116d04dSCyndy Ishida     std::vector<MetadataSection> AllowableClients;
9860116d04dSCyndy Ishida     std::vector<MetadataSection> ReexportedLibraries;
9870116d04dSCyndy Ishida     TBDFlags Flags{TBDFlags::None};
9880116d04dSCyndy Ishida     std::vector<UmbrellaSection> ParentUmbrellas;
9890116d04dSCyndy Ishida     SectionList Exports;
9900116d04dSCyndy Ishida     SectionList Reexports;
9910116d04dSCyndy Ishida     SectionList Undefineds;
9920116d04dSCyndy Ishida 
9930116d04dSCyndy Ishida   private:
assignTargetsToLibraryllvm::yaml::MappingTraits::NormalizedTBD_V49940116d04dSCyndy Ishida     void assignTargetsToLibrary(const std::vector<InterfaceFileRef> &Libraries,
9950116d04dSCyndy Ishida                                 std::vector<MetadataSection> &Section) {
9960116d04dSCyndy Ishida       std::set<TargetList> targetSet;
9970116d04dSCyndy Ishida       std::map<const InterfaceFileRef *, TargetList> valueToTargetList;
9980116d04dSCyndy Ishida       for (const auto &library : Libraries) {
9990116d04dSCyndy Ishida         TargetList targets(library.targets());
10000116d04dSCyndy Ishida         valueToTargetList[&library] = targets;
10010116d04dSCyndy Ishida         targetSet.emplace(std::move(targets));
10020116d04dSCyndy Ishida       }
10030116d04dSCyndy Ishida 
10040116d04dSCyndy Ishida       for (const auto &targets : targetSet) {
10050116d04dSCyndy Ishida         MetadataSection CurrentSection;
10060116d04dSCyndy Ishida         CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
10070116d04dSCyndy Ishida                                       targets.begin(), targets.end());
10080116d04dSCyndy Ishida 
10090116d04dSCyndy Ishida         for (const auto &it : valueToTargetList) {
10100116d04dSCyndy Ishida           if (it.second != targets)
10110116d04dSCyndy Ishida             continue;
10120116d04dSCyndy Ishida 
10130116d04dSCyndy Ishida           CurrentSection.Values.emplace_back(it.first->getInstallName());
10140116d04dSCyndy Ishida         }
10150116d04dSCyndy Ishida         llvm::sort(CurrentSection.Values);
10160116d04dSCyndy Ishida         Section.emplace_back(std::move(CurrentSection));
10170116d04dSCyndy Ishida       }
10180116d04dSCyndy Ishida     }
10190116d04dSCyndy Ishida   };
10200116d04dSCyndy Ishida 
mapKeysToValuesllvm::yaml::MappingTraits10210116d04dSCyndy Ishida   static void mapKeysToValues(FileType FileKind, IO &IO,
10220116d04dSCyndy Ishida                               const InterfaceFile *&File) {
10230116d04dSCyndy Ishida     MappingNormalization<NormalizedTBD, const InterfaceFile *> Keys(IO, File);
10240116d04dSCyndy Ishida     IO.mapRequired("archs", Keys->Architectures);
10250116d04dSCyndy Ishida     if (FileKind != FileType::TBD_V1)
10260116d04dSCyndy Ishida       IO.mapOptional("uuids", Keys->UUIDs);
10270116d04dSCyndy Ishida     IO.mapRequired("platform", Keys->Platforms);
10280116d04dSCyndy Ishida     if (FileKind != FileType::TBD_V1)
10290116d04dSCyndy Ishida       IO.mapOptional("flags", Keys->Flags, TBDFlags::None);
10300116d04dSCyndy Ishida     IO.mapRequired("install-name", Keys->InstallName);
10310116d04dSCyndy Ishida     IO.mapOptional("current-version", Keys->CurrentVersion,
10320116d04dSCyndy Ishida                    PackedVersion(1, 0, 0));
10330116d04dSCyndy Ishida     IO.mapOptional("compatibility-version", Keys->CompatibilityVersion,
10340116d04dSCyndy Ishida                    PackedVersion(1, 0, 0));
10350116d04dSCyndy Ishida     if (FileKind != FileType::TBD_V3)
10360116d04dSCyndy Ishida       IO.mapOptional("swift-version", Keys->SwiftABIVersion, SwiftVersion(0));
10370116d04dSCyndy Ishida     else
10380116d04dSCyndy Ishida       IO.mapOptional("swift-abi-version", Keys->SwiftABIVersion,
10390116d04dSCyndy Ishida                      SwiftVersion(0));
10400116d04dSCyndy Ishida     IO.mapOptional("objc-constraint", Keys->ObjCConstraint,
10410116d04dSCyndy Ishida                    (FileKind == FileType::TBD_V1)
10420116d04dSCyndy Ishida                        ? ObjCConstraintType::None
10430116d04dSCyndy Ishida                        : ObjCConstraintType::Retain_Release);
10440116d04dSCyndy Ishida     if (FileKind != FileType::TBD_V1)
10450116d04dSCyndy Ishida       IO.mapOptional("parent-umbrella", Keys->ParentUmbrella, StringRef());
10460116d04dSCyndy Ishida     IO.mapOptional("exports", Keys->Exports);
10470116d04dSCyndy Ishida     if (FileKind != FileType::TBD_V1)
10480116d04dSCyndy Ishida       IO.mapOptional("undefineds", Keys->Undefineds);
10490116d04dSCyndy Ishida   }
10500116d04dSCyndy Ishida 
mapKeysToValuesV4llvm::yaml::MappingTraits10510116d04dSCyndy Ishida   static void mapKeysToValuesV4(IO &IO, const InterfaceFile *&File) {
10520116d04dSCyndy Ishida     MappingNormalization<NormalizedTBD_V4, const InterfaceFile *> Keys(IO,
10530116d04dSCyndy Ishida                                                                        File);
10540116d04dSCyndy Ishida     IO.mapTag("!tapi-tbd", true);
10550116d04dSCyndy Ishida     IO.mapRequired("tbd-version", Keys->TBDVersion);
10560116d04dSCyndy Ishida     IO.mapRequired("targets", Keys->Targets);
10570116d04dSCyndy Ishida     IO.mapOptional("uuids", Keys->UUIDs);
10580116d04dSCyndy Ishida     IO.mapOptional("flags", Keys->Flags, TBDFlags::None);
10590116d04dSCyndy Ishida     IO.mapRequired("install-name", Keys->InstallName);
10600116d04dSCyndy Ishida     IO.mapOptional("current-version", Keys->CurrentVersion,
10610116d04dSCyndy Ishida                    PackedVersion(1, 0, 0));
10620116d04dSCyndy Ishida     IO.mapOptional("compatibility-version", Keys->CompatibilityVersion,
10630116d04dSCyndy Ishida                    PackedVersion(1, 0, 0));
10640116d04dSCyndy Ishida     IO.mapOptional("swift-abi-version", Keys->SwiftABIVersion, SwiftVersion(0));
10650116d04dSCyndy Ishida     IO.mapOptional("parent-umbrella", Keys->ParentUmbrellas);
10660116d04dSCyndy Ishida     auto OptionKind = MetadataSection::Option::Clients;
10670116d04dSCyndy Ishida     IO.mapOptionalWithContext("allowable-clients", Keys->AllowableClients,
10680116d04dSCyndy Ishida                               OptionKind);
10690116d04dSCyndy Ishida     OptionKind = MetadataSection::Option::Libraries;
10700116d04dSCyndy Ishida     IO.mapOptionalWithContext("reexported-libraries", Keys->ReexportedLibraries,
10710116d04dSCyndy Ishida                               OptionKind);
10720116d04dSCyndy Ishida     IO.mapOptional("exports", Keys->Exports);
10730116d04dSCyndy Ishida     IO.mapOptional("reexports", Keys->Reexports);
10740116d04dSCyndy Ishida     IO.mapOptional("undefineds", Keys->Undefineds);
10750116d04dSCyndy Ishida   }
10760116d04dSCyndy Ishida };
10770116d04dSCyndy Ishida 
10780116d04dSCyndy Ishida template <>
10790116d04dSCyndy Ishida struct DocumentListTraits<std::vector<const MachO::InterfaceFile *>> {
sizellvm::yaml::DocumentListTraits10800116d04dSCyndy Ishida   static size_t size(IO &IO, std::vector<const MachO::InterfaceFile *> &Seq) {
10810116d04dSCyndy Ishida     return Seq.size();
10820116d04dSCyndy Ishida   }
10830116d04dSCyndy Ishida   static const InterfaceFile *&
elementllvm::yaml::DocumentListTraits10840116d04dSCyndy Ishida   element(IO &IO, std::vector<const InterfaceFile *> &Seq, size_t Index) {
10850116d04dSCyndy Ishida     if (Index >= Seq.size())
10860116d04dSCyndy Ishida       Seq.resize(Index + 1);
10870116d04dSCyndy Ishida     return Seq[Index];
10880116d04dSCyndy Ishida   }
10890116d04dSCyndy Ishida };
10900116d04dSCyndy Ishida 
10910116d04dSCyndy Ishida } // end namespace yaml.
10920116d04dSCyndy Ishida } // namespace llvm
10930116d04dSCyndy Ishida 
DiagHandler(const SMDiagnostic & Diag,void * Context)10940116d04dSCyndy Ishida static void DiagHandler(const SMDiagnostic &Diag, void *Context) {
10950116d04dSCyndy Ishida   auto *File = static_cast<TextAPIContext *>(Context);
10960116d04dSCyndy Ishida   SmallString<1024> Message;
10970116d04dSCyndy Ishida   raw_svector_ostream S(Message);
10980116d04dSCyndy Ishida 
10990116d04dSCyndy Ishida   SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), File->Path,
11000116d04dSCyndy Ishida                        Diag.getLineNo(), Diag.getColumnNo(), Diag.getKind(),
11010116d04dSCyndy Ishida                        Diag.getMessage(), Diag.getLineContents(),
11020116d04dSCyndy Ishida                        Diag.getRanges(), Diag.getFixIts());
11030116d04dSCyndy Ishida 
11040116d04dSCyndy Ishida   NewDiag.print(nullptr, S);
11050116d04dSCyndy Ishida   File->ErrorMessage = ("malformed file\n" + Message).str();
11060116d04dSCyndy Ishida }
11070116d04dSCyndy Ishida 
11080116d04dSCyndy Ishida Expected<std::unique_ptr<InterfaceFile>>
get(MemoryBufferRef InputBuffer)11090116d04dSCyndy Ishida TextAPIReader::get(MemoryBufferRef InputBuffer) {
11100116d04dSCyndy Ishida   TextAPIContext Ctx;
11110116d04dSCyndy Ishida   Ctx.Path = std::string(InputBuffer.getBufferIdentifier());
11120116d04dSCyndy Ishida   yaml::Input YAMLIn(InputBuffer.getBuffer(), &Ctx, DiagHandler, &Ctx);
11130116d04dSCyndy Ishida 
11140116d04dSCyndy Ishida   // Fill vector with interface file objects created by parsing the YAML file.
11150116d04dSCyndy Ishida   std::vector<const InterfaceFile *> Files;
11160116d04dSCyndy Ishida   YAMLIn >> Files;
11170116d04dSCyndy Ishida 
11180116d04dSCyndy Ishida   // YAMLIn dynamically allocates for Interface file and in case of error,
11190116d04dSCyndy Ishida   // memory leak will occur unless wrapped around unique_ptr
11200116d04dSCyndy Ishida   auto File = std::unique_ptr<InterfaceFile>(
11210116d04dSCyndy Ishida       const_cast<InterfaceFile *>(Files.front()));
11220116d04dSCyndy Ishida 
1123cfc74024SKazu Hirata   for (const InterfaceFile *FI : llvm::drop_begin(Files))
11240116d04dSCyndy Ishida     File->addDocument(
1125cfc74024SKazu Hirata         std::shared_ptr<InterfaceFile>(const_cast<InterfaceFile *>(FI)));
11260116d04dSCyndy Ishida 
11270116d04dSCyndy Ishida   if (YAMLIn.error())
11280116d04dSCyndy Ishida     return make_error<StringError>(Ctx.ErrorMessage, YAMLIn.error());
11290116d04dSCyndy Ishida 
11300116d04dSCyndy Ishida   return std::move(File);
11310116d04dSCyndy Ishida }
11320116d04dSCyndy Ishida 
writeToStream(raw_ostream & OS,const InterfaceFile & File)11330116d04dSCyndy Ishida Error TextAPIWriter::writeToStream(raw_ostream &OS, const InterfaceFile &File) {
11340116d04dSCyndy Ishida   TextAPIContext Ctx;
11350116d04dSCyndy Ishida   Ctx.Path = std::string(File.getPath());
11360116d04dSCyndy Ishida   Ctx.FileKind = File.getFileType();
11370116d04dSCyndy Ishida   llvm::yaml::Output YAMLOut(OS, &Ctx, /*WrapColumn=*/80);
11380116d04dSCyndy Ishida 
11390116d04dSCyndy Ishida   std::vector<const InterfaceFile *> Files;
11400116d04dSCyndy Ishida   Files.emplace_back(&File);
11410116d04dSCyndy Ishida 
11420116d04dSCyndy Ishida   for (auto Document : File.documents())
11430116d04dSCyndy Ishida     Files.emplace_back(Document.get());
11440116d04dSCyndy Ishida 
11450116d04dSCyndy Ishida   // Stream out yaml.
11460116d04dSCyndy Ishida   YAMLOut << Files;
11470116d04dSCyndy Ishida 
11480116d04dSCyndy Ishida   return Error::success();
11490116d04dSCyndy Ishida }
1150