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__anon06c689540111::UUIDv42580116d04dSCyndy Ishida UUIDv4(const Target &TargetID, const std::string &Value)
2590116d04dSCyndy Ishida : TargetID(TargetID), Value(Value) {}
2600116d04dSCyndy Ishida };
2610116d04dSCyndy Ishida } // end anonymous namespace.
2620116d04dSCyndy Ishida
2630116d04dSCyndy Ishida LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(Architecture)
2640116d04dSCyndy Ishida LLVM_YAML_IS_SEQUENCE_VECTOR(ExportSection)
2650116d04dSCyndy Ishida LLVM_YAML_IS_SEQUENCE_VECTOR(UndefinedSection)
2660116d04dSCyndy Ishida // Specific to TBDv4
2670116d04dSCyndy Ishida LLVM_YAML_IS_SEQUENCE_VECTOR(SymbolSection)
2680116d04dSCyndy Ishida LLVM_YAML_IS_SEQUENCE_VECTOR(MetadataSection)
2690116d04dSCyndy Ishida LLVM_YAML_IS_SEQUENCE_VECTOR(UmbrellaSection)
2700116d04dSCyndy Ishida LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(Target)
2710116d04dSCyndy Ishida LLVM_YAML_IS_SEQUENCE_VECTOR(UUIDv4)
2720116d04dSCyndy Ishida
2730116d04dSCyndy Ishida namespace llvm {
2740116d04dSCyndy Ishida namespace yaml {
2750116d04dSCyndy Ishida
2760116d04dSCyndy Ishida template <> struct MappingTraits<ExportSection> {
mappingllvm::yaml::MappingTraits2770116d04dSCyndy Ishida static void mapping(IO &IO, ExportSection &Section) {
2780116d04dSCyndy Ishida const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
279*e6e93196STroy Butler assert((!Ctx || Ctx->FileKind != FileType::Invalid) &&
2800116d04dSCyndy Ishida "File type is not set in YAML context");
2810116d04dSCyndy Ishida
2820116d04dSCyndy Ishida IO.mapRequired("archs", Section.Architectures);
2830116d04dSCyndy Ishida if (Ctx->FileKind == FileType::TBD_V1)
2840116d04dSCyndy Ishida IO.mapOptional("allowed-clients", Section.AllowableClients);
2850116d04dSCyndy Ishida else
2860116d04dSCyndy Ishida IO.mapOptional("allowable-clients", Section.AllowableClients);
2870116d04dSCyndy Ishida IO.mapOptional("re-exports", Section.ReexportedLibraries);
2880116d04dSCyndy Ishida IO.mapOptional("symbols", Section.Symbols);
2890116d04dSCyndy Ishida IO.mapOptional("objc-classes", Section.Classes);
2900116d04dSCyndy Ishida if (Ctx->FileKind == FileType::TBD_V3)
2910116d04dSCyndy Ishida IO.mapOptional("objc-eh-types", Section.ClassEHs);
2920116d04dSCyndy Ishida IO.mapOptional("objc-ivars", Section.IVars);
2930116d04dSCyndy Ishida IO.mapOptional("weak-def-symbols", Section.WeakDefSymbols);
2940116d04dSCyndy Ishida IO.mapOptional("thread-local-symbols", Section.TLVSymbols);
2950116d04dSCyndy Ishida }
2960116d04dSCyndy Ishida };
2970116d04dSCyndy Ishida
2980116d04dSCyndy Ishida template <> struct MappingTraits<UndefinedSection> {
mappingllvm::yaml::MappingTraits2990116d04dSCyndy Ishida static void mapping(IO &IO, UndefinedSection &Section) {
3000116d04dSCyndy Ishida const auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
301*e6e93196STroy Butler assert((!Ctx || Ctx->FileKind != FileType::Invalid) &&
3020116d04dSCyndy Ishida "File type is not set in YAML context");
3030116d04dSCyndy Ishida
3040116d04dSCyndy Ishida IO.mapRequired("archs", Section.Architectures);
3050116d04dSCyndy Ishida IO.mapOptional("symbols", Section.Symbols);
3060116d04dSCyndy Ishida IO.mapOptional("objc-classes", Section.Classes);
3070116d04dSCyndy Ishida if (Ctx->FileKind == FileType::TBD_V3)
3080116d04dSCyndy Ishida IO.mapOptional("objc-eh-types", Section.ClassEHs);
3090116d04dSCyndy Ishida IO.mapOptional("objc-ivars", Section.IVars);
3100116d04dSCyndy Ishida IO.mapOptional("weak-ref-symbols", Section.WeakRefSymbols);
3110116d04dSCyndy Ishida }
3120116d04dSCyndy Ishida };
3130116d04dSCyndy Ishida
3140116d04dSCyndy Ishida template <> struct MappingTraits<SymbolSection> {
mappingllvm::yaml::MappingTraits3150116d04dSCyndy Ishida static void mapping(IO &IO, SymbolSection &Section) {
3160116d04dSCyndy Ishida IO.mapRequired("targets", Section.Targets);
3170116d04dSCyndy Ishida IO.mapOptional("symbols", Section.Symbols);
3180116d04dSCyndy Ishida IO.mapOptional("objc-classes", Section.Classes);
3190116d04dSCyndy Ishida IO.mapOptional("objc-eh-types", Section.ClassEHs);
3200116d04dSCyndy Ishida IO.mapOptional("objc-ivars", Section.Ivars);
3210116d04dSCyndy Ishida IO.mapOptional("weak-symbols", Section.WeakSymbols);
3220116d04dSCyndy Ishida IO.mapOptional("thread-local-symbols", Section.TlvSymbols);
3230116d04dSCyndy Ishida }
3240116d04dSCyndy Ishida };
3250116d04dSCyndy Ishida
3260116d04dSCyndy Ishida template <> struct MappingTraits<UmbrellaSection> {
mappingllvm::yaml::MappingTraits3270116d04dSCyndy Ishida static void mapping(IO &IO, UmbrellaSection &Section) {
3280116d04dSCyndy Ishida IO.mapRequired("targets", Section.Targets);
3290116d04dSCyndy Ishida IO.mapRequired("umbrella", Section.Umbrella);
3300116d04dSCyndy Ishida }
3310116d04dSCyndy Ishida };
3320116d04dSCyndy Ishida
3330116d04dSCyndy Ishida template <> struct MappingTraits<UUIDv4> {
mappingllvm::yaml::MappingTraits3340116d04dSCyndy Ishida static void mapping(IO &IO, UUIDv4 &UUID) {
3350116d04dSCyndy Ishida IO.mapRequired("target", UUID.TargetID);
3360116d04dSCyndy Ishida IO.mapRequired("value", UUID.Value);
3370116d04dSCyndy Ishida }
3380116d04dSCyndy Ishida };
3390116d04dSCyndy Ishida
3400116d04dSCyndy Ishida template <>
3410116d04dSCyndy Ishida struct MappingContextTraits<MetadataSection, MetadataSection::Option> {
mappingllvm::yaml::MappingContextTraits3420116d04dSCyndy Ishida static void mapping(IO &IO, MetadataSection &Section,
3430116d04dSCyndy Ishida MetadataSection::Option &OptionKind) {
3440116d04dSCyndy Ishida IO.mapRequired("targets", Section.Targets);
3450116d04dSCyndy Ishida switch (OptionKind) {
3460116d04dSCyndy Ishida case MetadataSection::Option::Clients:
3470116d04dSCyndy Ishida IO.mapRequired("clients", Section.Values);
3480116d04dSCyndy Ishida return;
3490116d04dSCyndy Ishida case MetadataSection::Option::Libraries:
3500116d04dSCyndy Ishida IO.mapRequired("libraries", Section.Values);
3510116d04dSCyndy Ishida return;
3520116d04dSCyndy Ishida }
3530116d04dSCyndy Ishida llvm_unreachable("unexpected option for metadata");
3540116d04dSCyndy Ishida }
3550116d04dSCyndy Ishida };
3560116d04dSCyndy Ishida
3570116d04dSCyndy Ishida template <> struct ScalarBitSetTraits<TBDFlags> {
bitsetllvm::yaml::ScalarBitSetTraits3580116d04dSCyndy Ishida static void bitset(IO &IO, TBDFlags &Flags) {
3590116d04dSCyndy Ishida IO.bitSetCase(Flags, "flat_namespace", TBDFlags::FlatNamespace);
3600116d04dSCyndy Ishida IO.bitSetCase(Flags, "not_app_extension_safe",
3610116d04dSCyndy Ishida TBDFlags::NotApplicationExtensionSafe);
3620116d04dSCyndy Ishida IO.bitSetCase(Flags, "installapi", TBDFlags::InstallAPI);
363e17efa60SCyndy Ishida IO.bitSetCase(Flags, "not_for_dyld_shared_cache",
364e17efa60SCyndy Ishida TBDFlags::OSLibNotForSharedCache);
3650116d04dSCyndy Ishida }
3660116d04dSCyndy Ishida };
3670116d04dSCyndy Ishida
3680116d04dSCyndy Ishida template <> struct ScalarTraits<Target> {
outputllvm::yaml::ScalarTraits3690116d04dSCyndy Ishida static void output(const Target &Value, void *, raw_ostream &OS) {
3700116d04dSCyndy Ishida OS << Value.Arch << "-";
3710116d04dSCyndy Ishida switch (Value.Platform) {
372bde2e698SJuergen Ributzka #define PLATFORM(platform, id, name, build_name, target, tapi_target, \
373bde2e698SJuergen Ributzka marketing) \
374bde2e698SJuergen Ributzka case PLATFORM_##platform: \
375bde2e698SJuergen Ributzka OS << #tapi_target; \
3760116d04dSCyndy Ishida break;
377bde2e698SJuergen Ributzka #include "llvm/BinaryFormat/MachO.def"
3780116d04dSCyndy Ishida }
3790116d04dSCyndy Ishida }
3800116d04dSCyndy Ishida
inputllvm::yaml::ScalarTraits3810116d04dSCyndy Ishida static StringRef input(StringRef Scalar, void *, Target &Value) {
3820116d04dSCyndy Ishida auto Result = Target::create(Scalar);
3830116d04dSCyndy Ishida if (!Result) {
3840116d04dSCyndy Ishida consumeError(Result.takeError());
3850116d04dSCyndy Ishida return "unparsable target";
3860116d04dSCyndy Ishida }
3870116d04dSCyndy Ishida
3880116d04dSCyndy Ishida Value = *Result;
3890116d04dSCyndy Ishida if (Value.Arch == AK_unknown)
3900116d04dSCyndy Ishida return "unknown architecture";
3913025c3edSJuergen Ributzka if (Value.Platform == PLATFORM_UNKNOWN)
3920116d04dSCyndy Ishida return "unknown platform";
3930116d04dSCyndy Ishida
3940116d04dSCyndy Ishida return {};
3950116d04dSCyndy Ishida }
3960116d04dSCyndy Ishida
mustQuotellvm::yaml::ScalarTraits3970116d04dSCyndy Ishida static QuotingType mustQuote(StringRef) { return QuotingType::None; }
3980116d04dSCyndy Ishida };
3990116d04dSCyndy Ishida
4000116d04dSCyndy Ishida template <> struct MappingTraits<const InterfaceFile *> {
4010116d04dSCyndy Ishida struct NormalizedTBD {
NormalizedTBDllvm::yaml::MappingTraits::NormalizedTBD4020116d04dSCyndy Ishida explicit NormalizedTBD(IO &IO) {}
NormalizedTBDllvm::yaml::MappingTraits::NormalizedTBD4030116d04dSCyndy Ishida NormalizedTBD(IO &IO, const InterfaceFile *&File) {
4040116d04dSCyndy Ishida Architectures = File->getArchitectures();
4050116d04dSCyndy Ishida Platforms = File->getPlatforms();
4060116d04dSCyndy Ishida InstallName = File->getInstallName();
4070116d04dSCyndy Ishida CurrentVersion = PackedVersion(File->getCurrentVersion());
4080116d04dSCyndy Ishida CompatibilityVersion = PackedVersion(File->getCompatibilityVersion());
4090116d04dSCyndy Ishida SwiftABIVersion = File->getSwiftABIVersion();
4100116d04dSCyndy Ishida ObjCConstraint = File->getObjCConstraint();
4110116d04dSCyndy Ishida
4120116d04dSCyndy Ishida Flags = TBDFlags::None;
4130116d04dSCyndy Ishida if (!File->isApplicationExtensionSafe())
4140116d04dSCyndy Ishida Flags |= TBDFlags::NotApplicationExtensionSafe;
4150116d04dSCyndy Ishida
4160116d04dSCyndy Ishida if (!File->isTwoLevelNamespace())
4170116d04dSCyndy Ishida Flags |= TBDFlags::FlatNamespace;
4180116d04dSCyndy Ishida
4190116d04dSCyndy Ishida if (!File->umbrellas().empty())
4200116d04dSCyndy Ishida ParentUmbrella = File->umbrellas().begin()->second;
4210116d04dSCyndy Ishida
4220116d04dSCyndy Ishida std::set<ArchitectureSet> ArchSet;
4230116d04dSCyndy Ishida for (const auto &Library : File->allowableClients())
4240116d04dSCyndy Ishida ArchSet.insert(Library.getArchitectures());
4250116d04dSCyndy Ishida
4260116d04dSCyndy Ishida for (const auto &Library : File->reexportedLibraries())
4270116d04dSCyndy Ishida ArchSet.insert(Library.getArchitectures());
4280116d04dSCyndy Ishida
4290116d04dSCyndy Ishida std::map<const Symbol *, ArchitectureSet> SymbolToArchSet;
4309b29de1cSCyndy Ishida for (const auto *Symbol : File->symbols()) {
4310116d04dSCyndy Ishida auto Architectures = Symbol->getArchitectures();
4320116d04dSCyndy Ishida SymbolToArchSet[Symbol] = Architectures;
4330116d04dSCyndy Ishida ArchSet.insert(Architectures);
4340116d04dSCyndy Ishida }
4350116d04dSCyndy Ishida
4360116d04dSCyndy Ishida for (auto Architectures : ArchSet) {
4370116d04dSCyndy Ishida ExportSection Section;
4380116d04dSCyndy Ishida Section.Architectures = Architectures;
4390116d04dSCyndy Ishida
4400116d04dSCyndy Ishida for (const auto &Library : File->allowableClients())
4410116d04dSCyndy Ishida if (Library.getArchitectures() == Architectures)
4420116d04dSCyndy Ishida Section.AllowableClients.emplace_back(Library.getInstallName());
4430116d04dSCyndy Ishida
4440116d04dSCyndy Ishida for (const auto &Library : File->reexportedLibraries())
4450116d04dSCyndy Ishida if (Library.getArchitectures() == Architectures)
4460116d04dSCyndy Ishida Section.ReexportedLibraries.emplace_back(Library.getInstallName());
4470116d04dSCyndy Ishida
4480116d04dSCyndy Ishida for (const auto &SymArch : SymbolToArchSet) {
4490116d04dSCyndy Ishida if (SymArch.second != Architectures)
4500116d04dSCyndy Ishida continue;
4510116d04dSCyndy Ishida
4520116d04dSCyndy Ishida const auto *Symbol = SymArch.first;
4530116d04dSCyndy Ishida switch (Symbol->getKind()) {
454d9a9872eSCyndy Ishida case EncodeKind::GlobalSymbol:
4550116d04dSCyndy Ishida if (Symbol->isWeakDefined())
4560116d04dSCyndy Ishida Section.WeakDefSymbols.emplace_back(Symbol->getName());
4570116d04dSCyndy Ishida else if (Symbol->isThreadLocalValue())
4580116d04dSCyndy Ishida Section.TLVSymbols.emplace_back(Symbol->getName());
4590116d04dSCyndy Ishida else
4600116d04dSCyndy Ishida Section.Symbols.emplace_back(Symbol->getName());
4610116d04dSCyndy Ishida break;
462d9a9872eSCyndy Ishida case EncodeKind::ObjectiveCClass:
4630116d04dSCyndy Ishida if (File->getFileType() != FileType::TBD_V3)
4640116d04dSCyndy Ishida Section.Classes.emplace_back(
4650116d04dSCyndy Ishida copyString("_" + Symbol->getName().str()));
4660116d04dSCyndy Ishida else
4670116d04dSCyndy Ishida Section.Classes.emplace_back(Symbol->getName());
4680116d04dSCyndy Ishida break;
469d9a9872eSCyndy Ishida case EncodeKind::ObjectiveCClassEHType:
4700116d04dSCyndy Ishida if (File->getFileType() != FileType::TBD_V3)
4710116d04dSCyndy Ishida Section.Symbols.emplace_back(
4720116d04dSCyndy Ishida copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str()));
4730116d04dSCyndy Ishida else
4740116d04dSCyndy Ishida Section.ClassEHs.emplace_back(Symbol->getName());
4750116d04dSCyndy Ishida break;
476d9a9872eSCyndy Ishida case EncodeKind::ObjectiveCInstanceVariable:
4770116d04dSCyndy Ishida if (File->getFileType() != FileType::TBD_V3)
4780116d04dSCyndy Ishida Section.IVars.emplace_back(
4790116d04dSCyndy Ishida copyString("_" + Symbol->getName().str()));
4800116d04dSCyndy Ishida else
4810116d04dSCyndy Ishida Section.IVars.emplace_back(Symbol->getName());
4820116d04dSCyndy Ishida break;
4830116d04dSCyndy Ishida }
4840116d04dSCyndy Ishida }
4850116d04dSCyndy Ishida llvm::sort(Section.Symbols);
4860116d04dSCyndy Ishida llvm::sort(Section.Classes);
4870116d04dSCyndy Ishida llvm::sort(Section.ClassEHs);
4880116d04dSCyndy Ishida llvm::sort(Section.IVars);
4890116d04dSCyndy Ishida llvm::sort(Section.WeakDefSymbols);
4900116d04dSCyndy Ishida llvm::sort(Section.TLVSymbols);
4910116d04dSCyndy Ishida Exports.emplace_back(std::move(Section));
4920116d04dSCyndy Ishida }
4930116d04dSCyndy Ishida
4940116d04dSCyndy Ishida ArchSet.clear();
4950116d04dSCyndy Ishida SymbolToArchSet.clear();
4960116d04dSCyndy Ishida
4970116d04dSCyndy Ishida for (const auto *Symbol : File->undefineds()) {
4980116d04dSCyndy Ishida auto Architectures = Symbol->getArchitectures();
4990116d04dSCyndy Ishida SymbolToArchSet[Symbol] = Architectures;
5000116d04dSCyndy Ishida ArchSet.insert(Architectures);
5010116d04dSCyndy Ishida }
5020116d04dSCyndy Ishida
5030116d04dSCyndy Ishida for (auto Architectures : ArchSet) {
5040116d04dSCyndy Ishida UndefinedSection Section;
5050116d04dSCyndy Ishida Section.Architectures = Architectures;
5060116d04dSCyndy Ishida
5070116d04dSCyndy Ishida for (const auto &SymArch : SymbolToArchSet) {
5080116d04dSCyndy Ishida if (SymArch.second != Architectures)
5090116d04dSCyndy Ishida continue;
5100116d04dSCyndy Ishida
5110116d04dSCyndy Ishida const auto *Symbol = SymArch.first;
5120116d04dSCyndy Ishida switch (Symbol->getKind()) {
513d9a9872eSCyndy Ishida case EncodeKind::GlobalSymbol:
5140116d04dSCyndy Ishida if (Symbol->isWeakReferenced())
5150116d04dSCyndy Ishida Section.WeakRefSymbols.emplace_back(Symbol->getName());
5160116d04dSCyndy Ishida else
5170116d04dSCyndy Ishida Section.Symbols.emplace_back(Symbol->getName());
5180116d04dSCyndy Ishida break;
519d9a9872eSCyndy Ishida case EncodeKind::ObjectiveCClass:
5200116d04dSCyndy Ishida if (File->getFileType() != FileType::TBD_V3)
5210116d04dSCyndy Ishida Section.Classes.emplace_back(
5220116d04dSCyndy Ishida copyString("_" + Symbol->getName().str()));
5230116d04dSCyndy Ishida else
5240116d04dSCyndy Ishida Section.Classes.emplace_back(Symbol->getName());
5250116d04dSCyndy Ishida break;
526d9a9872eSCyndy Ishida case EncodeKind::ObjectiveCClassEHType:
5270116d04dSCyndy Ishida if (File->getFileType() != FileType::TBD_V3)
5280116d04dSCyndy Ishida Section.Symbols.emplace_back(
5290116d04dSCyndy Ishida copyString("_OBJC_EHTYPE_$_" + Symbol->getName().str()));
5300116d04dSCyndy Ishida else
5310116d04dSCyndy Ishida Section.ClassEHs.emplace_back(Symbol->getName());
5320116d04dSCyndy Ishida break;
533d9a9872eSCyndy Ishida case EncodeKind::ObjectiveCInstanceVariable:
5340116d04dSCyndy Ishida if (File->getFileType() != FileType::TBD_V3)
5350116d04dSCyndy Ishida Section.IVars.emplace_back(
5360116d04dSCyndy Ishida copyString("_" + Symbol->getName().str()));
5370116d04dSCyndy Ishida else
5380116d04dSCyndy Ishida Section.IVars.emplace_back(Symbol->getName());
5390116d04dSCyndy Ishida break;
5400116d04dSCyndy Ishida }
5410116d04dSCyndy Ishida }
5420116d04dSCyndy Ishida llvm::sort(Section.Symbols);
5430116d04dSCyndy Ishida llvm::sort(Section.Classes);
5440116d04dSCyndy Ishida llvm::sort(Section.ClassEHs);
5450116d04dSCyndy Ishida llvm::sort(Section.IVars);
5460116d04dSCyndy Ishida llvm::sort(Section.WeakRefSymbols);
5470116d04dSCyndy Ishida Undefineds.emplace_back(std::move(Section));
5480116d04dSCyndy Ishida }
5490116d04dSCyndy Ishida }
5500116d04dSCyndy Ishida
5510116d04dSCyndy Ishida // TBD v1 - TBD v3 files only support one platform and several
5520116d04dSCyndy Ishida // architectures. It is possible to have more than one platform for TBD v3
5530116d04dSCyndy Ishida // files, but the architectures don't apply to all
5540116d04dSCyndy Ishida // platforms, specifically to filter out the i386 slice from
5550116d04dSCyndy Ishida // platform macCatalyst.
synthesizeTargetsllvm::yaml::MappingTraits::NormalizedTBD5560116d04dSCyndy Ishida TargetList synthesizeTargets(ArchitectureSet Architectures,
5570116d04dSCyndy Ishida const PlatformSet &Platforms) {
5580116d04dSCyndy Ishida TargetList Targets;
5590116d04dSCyndy Ishida
5600116d04dSCyndy Ishida for (auto Platform : Platforms) {
5613025c3edSJuergen Ributzka Platform = mapToPlatformType(Platform, Architectures.hasX86());
5620116d04dSCyndy Ishida
5630116d04dSCyndy Ishida for (const auto &&Architecture : Architectures) {
5643025c3edSJuergen Ributzka if ((Architecture == AK_i386) && (Platform == PLATFORM_MACCATALYST))
5650116d04dSCyndy Ishida continue;
5660116d04dSCyndy Ishida
5670116d04dSCyndy Ishida Targets.emplace_back(Architecture, Platform);
5680116d04dSCyndy Ishida }
5690116d04dSCyndy Ishida }
5700116d04dSCyndy Ishida return Targets;
5710116d04dSCyndy Ishida }
5720116d04dSCyndy Ishida
denormalizellvm::yaml::MappingTraits::NormalizedTBD5730116d04dSCyndy Ishida const InterfaceFile *denormalize(IO &IO) {
5740116d04dSCyndy Ishida auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
5750116d04dSCyndy Ishida assert(Ctx);
5760116d04dSCyndy Ishida
5770116d04dSCyndy Ishida auto *File = new InterfaceFile;
5780116d04dSCyndy Ishida File->setPath(Ctx->Path);
5790116d04dSCyndy Ishida File->setFileType(Ctx->FileKind);
5800116d04dSCyndy Ishida File->addTargets(synthesizeTargets(Architectures, Platforms));
5810116d04dSCyndy Ishida File->setInstallName(InstallName);
5820116d04dSCyndy Ishida File->setCurrentVersion(CurrentVersion);
5830116d04dSCyndy Ishida File->setCompatibilityVersion(CompatibilityVersion);
5840116d04dSCyndy Ishida File->setSwiftABIVersion(SwiftABIVersion);
5850116d04dSCyndy Ishida File->setObjCConstraint(ObjCConstraint);
5860116d04dSCyndy Ishida for (const auto &Target : File->targets())
5870116d04dSCyndy Ishida File->addParentUmbrella(Target, ParentUmbrella);
5880116d04dSCyndy Ishida
5890116d04dSCyndy Ishida if (Ctx->FileKind == FileType::TBD_V1) {
5900116d04dSCyndy Ishida File->setTwoLevelNamespace();
5910116d04dSCyndy Ishida File->setApplicationExtensionSafe();
5920116d04dSCyndy Ishida } else {
5930116d04dSCyndy Ishida File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
5940116d04dSCyndy Ishida File->setApplicationExtensionSafe(
5950116d04dSCyndy Ishida !(Flags & TBDFlags::NotApplicationExtensionSafe));
5960116d04dSCyndy Ishida }
5970116d04dSCyndy Ishida
598455bf3d1SCyndy Ishida // For older file formats, the segment where the symbol
599455bf3d1SCyndy Ishida // comes from is unknown, treat all symbols as Data
600455bf3d1SCyndy Ishida // in these cases.
601455bf3d1SCyndy Ishida const auto Flags = SymbolFlags::Data;
602455bf3d1SCyndy Ishida
6030116d04dSCyndy Ishida for (const auto &Section : Exports) {
6040116d04dSCyndy Ishida const auto Targets =
6050116d04dSCyndy Ishida synthesizeTargets(Section.Architectures, Platforms);
6060116d04dSCyndy Ishida
6070116d04dSCyndy Ishida for (const auto &Lib : Section.AllowableClients)
6080116d04dSCyndy Ishida for (const auto &Target : Targets)
6090116d04dSCyndy Ishida File->addAllowableClient(Lib, Target);
6100116d04dSCyndy Ishida
6110116d04dSCyndy Ishida for (const auto &Lib : Section.ReexportedLibraries)
6120116d04dSCyndy Ishida for (const auto &Target : Targets)
6130116d04dSCyndy Ishida File->addReexportedLibrary(Lib, Target);
6140116d04dSCyndy Ishida
6150116d04dSCyndy Ishida for (const auto &Symbol : Section.Symbols) {
6160116d04dSCyndy Ishida if (Ctx->FileKind != FileType::TBD_V3 &&
617586ecdf2SKazu Hirata Symbol.value.starts_with(ObjC2EHTypePrefix))
618d9a9872eSCyndy Ishida File->addSymbol(EncodeKind::ObjectiveCClassEHType,
619455bf3d1SCyndy Ishida Symbol.value.drop_front(15), Targets, Flags);
6200116d04dSCyndy Ishida else
621d9a9872eSCyndy Ishida File->addSymbol(EncodeKind::GlobalSymbol, Symbol, Targets, Flags);
6220116d04dSCyndy Ishida }
6230116d04dSCyndy Ishida for (auto &Symbol : Section.Classes) {
6240116d04dSCyndy Ishida auto Name = Symbol.value;
6250116d04dSCyndy Ishida if (Ctx->FileKind != FileType::TBD_V3)
6260116d04dSCyndy Ishida Name = Name.drop_front();
627d9a9872eSCyndy Ishida File->addSymbol(EncodeKind::ObjectiveCClass, Name, Targets, Flags);
6280116d04dSCyndy Ishida }
6290116d04dSCyndy Ishida for (auto &Symbol : Section.ClassEHs)
630d9a9872eSCyndy Ishida File->addSymbol(EncodeKind::ObjectiveCClassEHType, Symbol, Targets,
631455bf3d1SCyndy Ishida Flags);
6320116d04dSCyndy Ishida for (auto &Symbol : Section.IVars) {
6330116d04dSCyndy Ishida auto Name = Symbol.value;
6340116d04dSCyndy Ishida if (Ctx->FileKind != FileType::TBD_V3)
6350116d04dSCyndy Ishida Name = Name.drop_front();
636d9a9872eSCyndy Ishida File->addSymbol(EncodeKind::ObjectiveCInstanceVariable, Name, Targets,
637455bf3d1SCyndy Ishida Flags);
6380116d04dSCyndy Ishida }
6390116d04dSCyndy Ishida for (auto &Symbol : Section.WeakDefSymbols)
640d9a9872eSCyndy Ishida File->addSymbol(EncodeKind::GlobalSymbol, Symbol, Targets,
641dc787bc9SCyndy Ishida SymbolFlags::WeakDefined | Flags);
6420116d04dSCyndy Ishida for (auto &Symbol : Section.TLVSymbols)
643d9a9872eSCyndy Ishida File->addSymbol(EncodeKind::GlobalSymbol, Symbol, Targets,
644dc787bc9SCyndy Ishida SymbolFlags::ThreadLocalValue | Flags);
6450116d04dSCyndy Ishida }
6460116d04dSCyndy Ishida
6470116d04dSCyndy Ishida for (const auto &Section : Undefineds) {
6480116d04dSCyndy Ishida const auto Targets =
6490116d04dSCyndy Ishida synthesizeTargets(Section.Architectures, Platforms);
6500116d04dSCyndy Ishida for (auto &Symbol : Section.Symbols) {
6510116d04dSCyndy Ishida if (Ctx->FileKind != FileType::TBD_V3 &&
652586ecdf2SKazu Hirata Symbol.value.starts_with(ObjC2EHTypePrefix))
653d9a9872eSCyndy Ishida File->addSymbol(EncodeKind::ObjectiveCClassEHType,
6540116d04dSCyndy Ishida Symbol.value.drop_front(15), Targets,
655455bf3d1SCyndy Ishida SymbolFlags::Undefined | Flags);
6560116d04dSCyndy Ishida else
657d9a9872eSCyndy Ishida File->addSymbol(EncodeKind::GlobalSymbol, Symbol, Targets,
658455bf3d1SCyndy Ishida SymbolFlags::Undefined | Flags);
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();
664d9a9872eSCyndy Ishida File->addSymbol(EncodeKind::ObjectiveCClass, Name, Targets,
665455bf3d1SCyndy Ishida SymbolFlags::Undefined | Flags);
6660116d04dSCyndy Ishida }
6670116d04dSCyndy Ishida for (auto &Symbol : Section.ClassEHs)
668d9a9872eSCyndy Ishida File->addSymbol(EncodeKind::ObjectiveCClassEHType, Symbol, Targets,
669455bf3d1SCyndy Ishida SymbolFlags::Undefined | Flags);
6700116d04dSCyndy Ishida for (auto &Symbol : Section.IVars) {
6710116d04dSCyndy Ishida auto Name = Symbol.value;
6720116d04dSCyndy Ishida if (Ctx->FileKind != FileType::TBD_V3)
6730116d04dSCyndy Ishida Name = Name.drop_front();
674d9a9872eSCyndy Ishida File->addSymbol(EncodeKind::ObjectiveCInstanceVariable, Name, Targets,
675455bf3d1SCyndy Ishida SymbolFlags::Undefined | Flags);
6760116d04dSCyndy Ishida }
6770116d04dSCyndy Ishida for (auto &Symbol : Section.WeakRefSymbols)
678d9a9872eSCyndy Ishida File->addSymbol(EncodeKind::GlobalSymbol, Symbol, Targets,
679455bf3d1SCyndy Ishida SymbolFlags::Undefined | SymbolFlags::WeakReferenced |
680455bf3d1SCyndy Ishida Flags);
6810116d04dSCyndy Ishida }
6820116d04dSCyndy Ishida
6830116d04dSCyndy Ishida return File;
6840116d04dSCyndy Ishida }
6850116d04dSCyndy Ishida
6860116d04dSCyndy Ishida llvm::BumpPtrAllocator Allocator;
copyStringllvm::yaml::MappingTraits::NormalizedTBD6870116d04dSCyndy Ishida StringRef copyString(StringRef String) {
6880116d04dSCyndy Ishida if (String.empty())
6890116d04dSCyndy Ishida return {};
6900116d04dSCyndy Ishida
6910116d04dSCyndy Ishida void *Ptr = Allocator.Allocate(String.size(), 1);
6920116d04dSCyndy Ishida memcpy(Ptr, String.data(), String.size());
6930116d04dSCyndy Ishida return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
6940116d04dSCyndy Ishida }
6950116d04dSCyndy Ishida
6960116d04dSCyndy Ishida std::vector<Architecture> Architectures;
6970116d04dSCyndy Ishida std::vector<UUID> UUIDs;
6980116d04dSCyndy Ishida PlatformSet Platforms;
6990116d04dSCyndy Ishida StringRef InstallName;
7000116d04dSCyndy Ishida PackedVersion CurrentVersion;
7010116d04dSCyndy Ishida PackedVersion CompatibilityVersion;
7020116d04dSCyndy Ishida SwiftVersion SwiftABIVersion{0};
7030116d04dSCyndy Ishida ObjCConstraintType ObjCConstraint{ObjCConstraintType::None};
7040116d04dSCyndy Ishida TBDFlags Flags{TBDFlags::None};
7050116d04dSCyndy Ishida StringRef ParentUmbrella;
7060116d04dSCyndy Ishida std::vector<ExportSection> Exports;
7070116d04dSCyndy Ishida std::vector<UndefinedSection> Undefineds;
7080116d04dSCyndy Ishida };
7090116d04dSCyndy Ishida
setFileTypeForInputllvm::yaml::MappingTraits7100116d04dSCyndy Ishida static void setFileTypeForInput(TextAPIContext *Ctx, IO &IO) {
7110116d04dSCyndy Ishida if (IO.mapTag("!tapi-tbd", false))
7120116d04dSCyndy Ishida Ctx->FileKind = FileType::TBD_V4;
7130116d04dSCyndy Ishida else if (IO.mapTag("!tapi-tbd-v3", false))
7140116d04dSCyndy Ishida Ctx->FileKind = FileType::TBD_V3;
7150116d04dSCyndy Ishida else if (IO.mapTag("!tapi-tbd-v2", false))
7160116d04dSCyndy Ishida Ctx->FileKind = FileType::TBD_V2;
7170116d04dSCyndy Ishida else if (IO.mapTag("!tapi-tbd-v1", false) ||
7180116d04dSCyndy Ishida IO.mapTag("tag:yaml.org,2002:map", false))
7190116d04dSCyndy Ishida Ctx->FileKind = FileType::TBD_V1;
7200116d04dSCyndy Ishida else {
7210116d04dSCyndy Ishida Ctx->FileKind = FileType::Invalid;
7220116d04dSCyndy Ishida return;
7230116d04dSCyndy Ishida }
7240116d04dSCyndy Ishida }
7250116d04dSCyndy Ishida
mappingllvm::yaml::MappingTraits7260116d04dSCyndy Ishida static void mapping(IO &IO, const InterfaceFile *&File) {
7270116d04dSCyndy Ishida auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
7280116d04dSCyndy Ishida assert((!Ctx || !IO.outputting() ||
7290116d04dSCyndy Ishida (Ctx && Ctx->FileKind != FileType::Invalid)) &&
7300116d04dSCyndy Ishida "File type is not set in YAML context");
7310116d04dSCyndy Ishida
7320116d04dSCyndy Ishida if (!IO.outputting()) {
7330116d04dSCyndy Ishida setFileTypeForInput(Ctx, IO);
7340116d04dSCyndy Ishida switch (Ctx->FileKind) {
7350116d04dSCyndy Ishida default:
7360116d04dSCyndy Ishida break;
7370116d04dSCyndy Ishida case FileType::TBD_V4:
7380116d04dSCyndy Ishida mapKeysToValuesV4(IO, File);
7390116d04dSCyndy Ishida return;
7400116d04dSCyndy Ishida case FileType::Invalid:
7410116d04dSCyndy Ishida IO.setError("unsupported file type");
7420116d04dSCyndy Ishida return;
7430116d04dSCyndy Ishida }
7440116d04dSCyndy Ishida } else {
7450116d04dSCyndy Ishida // Set file type when writing.
7460116d04dSCyndy Ishida switch (Ctx->FileKind) {
7470116d04dSCyndy Ishida default:
7480116d04dSCyndy Ishida llvm_unreachable("unexpected file type");
7490116d04dSCyndy Ishida case FileType::TBD_V4:
7500116d04dSCyndy Ishida mapKeysToValuesV4(IO, File);
7510116d04dSCyndy Ishida return;
7520116d04dSCyndy Ishida case FileType::TBD_V3:
7530116d04dSCyndy Ishida IO.mapTag("!tapi-tbd-v3", true);
7540116d04dSCyndy Ishida break;
7550116d04dSCyndy Ishida case FileType::TBD_V2:
7560116d04dSCyndy Ishida IO.mapTag("!tapi-tbd-v2", true);
7570116d04dSCyndy Ishida break;
7580116d04dSCyndy Ishida case FileType::TBD_V1:
7590116d04dSCyndy Ishida // Don't write the tag into the .tbd file for TBD v1
7600116d04dSCyndy Ishida break;
7610116d04dSCyndy Ishida }
7620116d04dSCyndy Ishida }
7630116d04dSCyndy Ishida mapKeysToValues(Ctx->FileKind, IO, File);
7640116d04dSCyndy Ishida }
7650116d04dSCyndy Ishida
7660116d04dSCyndy Ishida using SectionList = std::vector<SymbolSection>;
7670116d04dSCyndy Ishida struct NormalizedTBD_V4 {
NormalizedTBD_V4llvm::yaml::MappingTraits::NormalizedTBD_V47680116d04dSCyndy Ishida explicit NormalizedTBD_V4(IO &IO) {}
NormalizedTBD_V4llvm::yaml::MappingTraits::NormalizedTBD_V47690116d04dSCyndy Ishida NormalizedTBD_V4(IO &IO, const InterfaceFile *&File) {
7700116d04dSCyndy Ishida auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
7710116d04dSCyndy Ishida assert(Ctx);
77227459a3aSCyndy Ishida TBDVersion = Ctx->FileKind >> 4;
7730116d04dSCyndy Ishida Targets.insert(Targets.begin(), File->targets().begin(),
7740116d04dSCyndy Ishida File->targets().end());
7750116d04dSCyndy Ishida InstallName = File->getInstallName();
7760116d04dSCyndy Ishida CurrentVersion = File->getCurrentVersion();
7770116d04dSCyndy Ishida CompatibilityVersion = File->getCompatibilityVersion();
7780116d04dSCyndy Ishida SwiftABIVersion = File->getSwiftABIVersion();
7790116d04dSCyndy Ishida
7800116d04dSCyndy Ishida Flags = TBDFlags::None;
7810116d04dSCyndy Ishida if (!File->isApplicationExtensionSafe())
7820116d04dSCyndy Ishida Flags |= TBDFlags::NotApplicationExtensionSafe;
7830116d04dSCyndy Ishida
7840116d04dSCyndy Ishida if (!File->isTwoLevelNamespace())
7850116d04dSCyndy Ishida Flags |= TBDFlags::FlatNamespace;
7860116d04dSCyndy Ishida
787e17efa60SCyndy Ishida if (File->isOSLibNotForSharedCache())
788e17efa60SCyndy Ishida Flags |= TBDFlags::OSLibNotForSharedCache;
789e17efa60SCyndy Ishida
7900116d04dSCyndy Ishida {
7910116d04dSCyndy Ishida std::map<std::string, TargetList> valueToTargetList;
7920116d04dSCyndy Ishida for (const auto &it : File->umbrellas())
7930116d04dSCyndy Ishida valueToTargetList[it.second].emplace_back(it.first);
7940116d04dSCyndy Ishida
7950116d04dSCyndy Ishida for (const auto &it : valueToTargetList) {
7960116d04dSCyndy Ishida UmbrellaSection CurrentSection;
7970116d04dSCyndy Ishida CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
7980116d04dSCyndy Ishida it.second.begin(), it.second.end());
7990116d04dSCyndy Ishida CurrentSection.Umbrella = it.first;
8000116d04dSCyndy Ishida ParentUmbrellas.emplace_back(std::move(CurrentSection));
8010116d04dSCyndy Ishida }
8020116d04dSCyndy Ishida }
8030116d04dSCyndy Ishida
8040116d04dSCyndy Ishida assignTargetsToLibrary(File->allowableClients(), AllowableClients);
8050116d04dSCyndy Ishida assignTargetsToLibrary(File->reexportedLibraries(), ReexportedLibraries);
8060116d04dSCyndy Ishida
8070116d04dSCyndy Ishida auto handleSymbols =
8080116d04dSCyndy Ishida [](SectionList &CurrentSections,
8099b29de1cSCyndy Ishida InterfaceFile::const_filtered_symbol_range Symbols) {
8100116d04dSCyndy Ishida std::set<TargetList> TargetSet;
8110116d04dSCyndy Ishida std::map<const Symbol *, TargetList> SymbolToTargetList;
8120116d04dSCyndy Ishida for (const auto *Symbol : Symbols) {
8130116d04dSCyndy Ishida TargetList Targets(Symbol->targets());
8140116d04dSCyndy Ishida SymbolToTargetList[Symbol] = Targets;
8150116d04dSCyndy Ishida TargetSet.emplace(std::move(Targets));
8160116d04dSCyndy Ishida }
8170116d04dSCyndy Ishida for (const auto &TargetIDs : TargetSet) {
8180116d04dSCyndy Ishida SymbolSection CurrentSection;
8190116d04dSCyndy Ishida CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
8200116d04dSCyndy Ishida TargetIDs.begin(), TargetIDs.end());
8210116d04dSCyndy Ishida
8220116d04dSCyndy Ishida for (const auto &IT : SymbolToTargetList) {
8230116d04dSCyndy Ishida if (IT.second != TargetIDs)
8240116d04dSCyndy Ishida continue;
8250116d04dSCyndy Ishida
8260116d04dSCyndy Ishida const auto *Symbol = IT.first;
8270116d04dSCyndy Ishida switch (Symbol->getKind()) {
828d9a9872eSCyndy Ishida case EncodeKind::GlobalSymbol:
8290116d04dSCyndy Ishida if (Symbol->isWeakDefined())
8300116d04dSCyndy Ishida CurrentSection.WeakSymbols.emplace_back(Symbol->getName());
8310116d04dSCyndy Ishida else if (Symbol->isThreadLocalValue())
8320116d04dSCyndy Ishida CurrentSection.TlvSymbols.emplace_back(Symbol->getName());
8330116d04dSCyndy Ishida else
8340116d04dSCyndy Ishida CurrentSection.Symbols.emplace_back(Symbol->getName());
8350116d04dSCyndy Ishida break;
836d9a9872eSCyndy Ishida case EncodeKind::ObjectiveCClass:
8370116d04dSCyndy Ishida CurrentSection.Classes.emplace_back(Symbol->getName());
8380116d04dSCyndy Ishida break;
839d9a9872eSCyndy Ishida case EncodeKind::ObjectiveCClassEHType:
8400116d04dSCyndy Ishida CurrentSection.ClassEHs.emplace_back(Symbol->getName());
8410116d04dSCyndy Ishida break;
842d9a9872eSCyndy Ishida case EncodeKind::ObjectiveCInstanceVariable:
8430116d04dSCyndy Ishida CurrentSection.Ivars.emplace_back(Symbol->getName());
8440116d04dSCyndy Ishida break;
8450116d04dSCyndy Ishida }
8460116d04dSCyndy Ishida }
8470116d04dSCyndy Ishida sort(CurrentSection.Symbols);
8480116d04dSCyndy Ishida sort(CurrentSection.Classes);
8490116d04dSCyndy Ishida sort(CurrentSection.ClassEHs);
8500116d04dSCyndy Ishida sort(CurrentSection.Ivars);
8510116d04dSCyndy Ishida sort(CurrentSection.WeakSymbols);
8520116d04dSCyndy Ishida sort(CurrentSection.TlvSymbols);
8530116d04dSCyndy Ishida CurrentSections.emplace_back(std::move(CurrentSection));
8540116d04dSCyndy Ishida }
8550116d04dSCyndy Ishida };
8560116d04dSCyndy Ishida
8579b29de1cSCyndy Ishida handleSymbols(Exports, File->exports());
8589b29de1cSCyndy Ishida handleSymbols(Reexports, File->reexports());
8599b29de1cSCyndy Ishida handleSymbols(Undefineds, File->undefineds());
8600116d04dSCyndy Ishida }
8610116d04dSCyndy Ishida
denormalizellvm::yaml::MappingTraits::NormalizedTBD_V48620116d04dSCyndy Ishida const InterfaceFile *denormalize(IO &IO) {
8630116d04dSCyndy Ishida auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext());
8640116d04dSCyndy Ishida assert(Ctx);
8650116d04dSCyndy Ishida
8660116d04dSCyndy Ishida auto *File = new InterfaceFile;
8670116d04dSCyndy Ishida File->setPath(Ctx->Path);
8680116d04dSCyndy Ishida File->setFileType(Ctx->FileKind);
8690116d04dSCyndy Ishida File->addTargets(Targets);
8700116d04dSCyndy Ishida File->setInstallName(InstallName);
8710116d04dSCyndy Ishida File->setCurrentVersion(CurrentVersion);
8720116d04dSCyndy Ishida File->setCompatibilityVersion(CompatibilityVersion);
8730116d04dSCyndy Ishida File->setSwiftABIVersion(SwiftABIVersion);
8740116d04dSCyndy Ishida for (const auto &CurrentSection : ParentUmbrellas)
8750116d04dSCyndy Ishida for (const auto &target : CurrentSection.Targets)
8760116d04dSCyndy Ishida File->addParentUmbrella(target, CurrentSection.Umbrella);
8770116d04dSCyndy Ishida File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
8780116d04dSCyndy Ishida File->setApplicationExtensionSafe(
8790116d04dSCyndy Ishida !(Flags & TBDFlags::NotApplicationExtensionSafe));
880e17efa60SCyndy Ishida File->setOSLibNotForSharedCache(
881e17efa60SCyndy Ishida (Flags & TBDFlags::OSLibNotForSharedCache));
8820116d04dSCyndy Ishida
8830116d04dSCyndy Ishida for (const auto &CurrentSection : AllowableClients) {
8840116d04dSCyndy Ishida for (const auto &lib : CurrentSection.Values)
8850116d04dSCyndy Ishida for (const auto &Target : CurrentSection.Targets)
8860116d04dSCyndy Ishida File->addAllowableClient(lib, Target);
8870116d04dSCyndy Ishida }
8880116d04dSCyndy Ishida
8890116d04dSCyndy Ishida for (const auto &CurrentSection : ReexportedLibraries) {
8900116d04dSCyndy Ishida for (const auto &Lib : CurrentSection.Values)
8910116d04dSCyndy Ishida for (const auto &Target : CurrentSection.Targets)
8920116d04dSCyndy Ishida File->addReexportedLibrary(Lib, Target);
8930116d04dSCyndy Ishida }
8940116d04dSCyndy Ishida
8950116d04dSCyndy Ishida auto handleSymbols = [File](const SectionList &CurrentSections,
896455bf3d1SCyndy Ishida SymbolFlags InputFlag = SymbolFlags::None) {
897455bf3d1SCyndy Ishida // For older file formats, the segment where the symbol
898455bf3d1SCyndy Ishida // comes from is unknown, treat all symbols as Data
899455bf3d1SCyndy Ishida // in these cases.
900455bf3d1SCyndy Ishida const SymbolFlags Flag = InputFlag | SymbolFlags::Data;
901455bf3d1SCyndy Ishida
9020116d04dSCyndy Ishida for (const auto &CurrentSection : CurrentSections) {
9030116d04dSCyndy Ishida for (auto &sym : CurrentSection.Symbols)
904d9a9872eSCyndy Ishida File->addSymbol(EncodeKind::GlobalSymbol, sym,
9050116d04dSCyndy Ishida CurrentSection.Targets, Flag);
9060116d04dSCyndy Ishida
9070116d04dSCyndy Ishida for (auto &sym : CurrentSection.Classes)
908d9a9872eSCyndy Ishida File->addSymbol(EncodeKind::ObjectiveCClass, sym,
9099b29de1cSCyndy Ishida CurrentSection.Targets, Flag);
9100116d04dSCyndy Ishida
9110116d04dSCyndy Ishida for (auto &sym : CurrentSection.ClassEHs)
912d9a9872eSCyndy Ishida File->addSymbol(EncodeKind::ObjectiveCClassEHType, sym,
9139b29de1cSCyndy Ishida CurrentSection.Targets, Flag);
9140116d04dSCyndy Ishida
9150116d04dSCyndy Ishida for (auto &sym : CurrentSection.Ivars)
916d9a9872eSCyndy Ishida File->addSymbol(EncodeKind::ObjectiveCInstanceVariable, sym,
9179b29de1cSCyndy Ishida CurrentSection.Targets, Flag);
9180116d04dSCyndy Ishida
919455bf3d1SCyndy Ishida SymbolFlags SymFlag =
920455bf3d1SCyndy Ishida ((Flag & SymbolFlags::Undefined) == SymbolFlags::Undefined)
9219b29de1cSCyndy Ishida ? SymbolFlags::WeakReferenced
9229b29de1cSCyndy Ishida : SymbolFlags::WeakDefined;
9239b29de1cSCyndy Ishida for (auto &sym : CurrentSection.WeakSymbols) {
924d9a9872eSCyndy Ishida File->addSymbol(EncodeKind::GlobalSymbol, sym,
9259b29de1cSCyndy Ishida CurrentSection.Targets, Flag | SymFlag);
9269b29de1cSCyndy Ishida }
9270116d04dSCyndy Ishida
9280116d04dSCyndy Ishida for (auto &sym : CurrentSection.TlvSymbols)
929d9a9872eSCyndy Ishida File->addSymbol(EncodeKind::GlobalSymbol, sym,
9300116d04dSCyndy Ishida CurrentSection.Targets,
9319b29de1cSCyndy Ishida Flag | SymbolFlags::ThreadLocalValue);
9320116d04dSCyndy Ishida }
9330116d04dSCyndy Ishida };
9340116d04dSCyndy Ishida
9350116d04dSCyndy Ishida handleSymbols(Exports);
9360116d04dSCyndy Ishida handleSymbols(Reexports, SymbolFlags::Rexported);
9370116d04dSCyndy Ishida handleSymbols(Undefineds, SymbolFlags::Undefined);
9380116d04dSCyndy Ishida
9390116d04dSCyndy Ishida return File;
9400116d04dSCyndy Ishida }
9410116d04dSCyndy Ishida
9420116d04dSCyndy Ishida unsigned TBDVersion;
9430116d04dSCyndy Ishida std::vector<UUIDv4> UUIDs;
9440116d04dSCyndy Ishida TargetList Targets;
9450116d04dSCyndy Ishida StringRef InstallName;
9460116d04dSCyndy Ishida PackedVersion CurrentVersion;
9470116d04dSCyndy Ishida PackedVersion CompatibilityVersion;
9480116d04dSCyndy Ishida SwiftVersion SwiftABIVersion{0};
9490116d04dSCyndy Ishida std::vector<MetadataSection> AllowableClients;
9500116d04dSCyndy Ishida std::vector<MetadataSection> ReexportedLibraries;
9510116d04dSCyndy Ishida TBDFlags Flags{TBDFlags::None};
9520116d04dSCyndy Ishida std::vector<UmbrellaSection> ParentUmbrellas;
9530116d04dSCyndy Ishida SectionList Exports;
9540116d04dSCyndy Ishida SectionList Reexports;
9550116d04dSCyndy Ishida SectionList Undefineds;
9560116d04dSCyndy Ishida
9570116d04dSCyndy Ishida private:
assignTargetsToLibraryllvm::yaml::MappingTraits::NormalizedTBD_V49580116d04dSCyndy Ishida void assignTargetsToLibrary(const std::vector<InterfaceFileRef> &Libraries,
9590116d04dSCyndy Ishida std::vector<MetadataSection> &Section) {
9600116d04dSCyndy Ishida std::set<TargetList> targetSet;
9610116d04dSCyndy Ishida std::map<const InterfaceFileRef *, TargetList> valueToTargetList;
9620116d04dSCyndy Ishida for (const auto &library : Libraries) {
9630116d04dSCyndy Ishida TargetList targets(library.targets());
9640116d04dSCyndy Ishida valueToTargetList[&library] = targets;
9650116d04dSCyndy Ishida targetSet.emplace(std::move(targets));
9660116d04dSCyndy Ishida }
9670116d04dSCyndy Ishida
9680116d04dSCyndy Ishida for (const auto &targets : targetSet) {
9690116d04dSCyndy Ishida MetadataSection CurrentSection;
9700116d04dSCyndy Ishida CurrentSection.Targets.insert(CurrentSection.Targets.begin(),
9710116d04dSCyndy Ishida targets.begin(), targets.end());
9720116d04dSCyndy Ishida
9730116d04dSCyndy Ishida for (const auto &it : valueToTargetList) {
9740116d04dSCyndy Ishida if (it.second != targets)
9750116d04dSCyndy Ishida continue;
9760116d04dSCyndy Ishida
9770116d04dSCyndy Ishida CurrentSection.Values.emplace_back(it.first->getInstallName());
9780116d04dSCyndy Ishida }
9790116d04dSCyndy Ishida llvm::sort(CurrentSection.Values);
9800116d04dSCyndy Ishida Section.emplace_back(std::move(CurrentSection));
9810116d04dSCyndy Ishida }
9820116d04dSCyndy Ishida }
9830116d04dSCyndy Ishida };
9840116d04dSCyndy Ishida
mapKeysToValuesllvm::yaml::MappingTraits9850116d04dSCyndy Ishida static void mapKeysToValues(FileType FileKind, IO &IO,
9860116d04dSCyndy Ishida const InterfaceFile *&File) {
9870116d04dSCyndy Ishida MappingNormalization<NormalizedTBD, const InterfaceFile *> Keys(IO, File);
988a0666956SCyndy Ishida std::vector<UUID> EmptyUUID;
9890116d04dSCyndy Ishida IO.mapRequired("archs", Keys->Architectures);
9900116d04dSCyndy Ishida if (FileKind != FileType::TBD_V1)
991a0666956SCyndy Ishida IO.mapOptional("uuids", EmptyUUID);
9920116d04dSCyndy Ishida IO.mapRequired("platform", Keys->Platforms);
9930116d04dSCyndy Ishida if (FileKind != FileType::TBD_V1)
9940116d04dSCyndy Ishida IO.mapOptional("flags", Keys->Flags, TBDFlags::None);
9950116d04dSCyndy Ishida IO.mapRequired("install-name", Keys->InstallName);
9960116d04dSCyndy Ishida IO.mapOptional("current-version", Keys->CurrentVersion,
9970116d04dSCyndy Ishida PackedVersion(1, 0, 0));
9980116d04dSCyndy Ishida IO.mapOptional("compatibility-version", Keys->CompatibilityVersion,
9990116d04dSCyndy Ishida PackedVersion(1, 0, 0));
10000116d04dSCyndy Ishida if (FileKind != FileType::TBD_V3)
10010116d04dSCyndy Ishida IO.mapOptional("swift-version", Keys->SwiftABIVersion, SwiftVersion(0));
10020116d04dSCyndy Ishida else
10030116d04dSCyndy Ishida IO.mapOptional("swift-abi-version", Keys->SwiftABIVersion,
10040116d04dSCyndy Ishida SwiftVersion(0));
10050116d04dSCyndy Ishida IO.mapOptional("objc-constraint", Keys->ObjCConstraint,
10060116d04dSCyndy Ishida (FileKind == FileType::TBD_V1)
10070116d04dSCyndy Ishida ? ObjCConstraintType::None
10080116d04dSCyndy Ishida : ObjCConstraintType::Retain_Release);
10090116d04dSCyndy Ishida if (FileKind != FileType::TBD_V1)
10100116d04dSCyndy Ishida IO.mapOptional("parent-umbrella", Keys->ParentUmbrella, StringRef());
10110116d04dSCyndy Ishida IO.mapOptional("exports", Keys->Exports);
10120116d04dSCyndy Ishida if (FileKind != FileType::TBD_V1)
10130116d04dSCyndy Ishida IO.mapOptional("undefineds", Keys->Undefineds);
10140116d04dSCyndy Ishida }
10150116d04dSCyndy Ishida
mapKeysToValuesV4llvm::yaml::MappingTraits10160116d04dSCyndy Ishida static void mapKeysToValuesV4(IO &IO, const InterfaceFile *&File) {
10170116d04dSCyndy Ishida MappingNormalization<NormalizedTBD_V4, const InterfaceFile *> Keys(IO,
10180116d04dSCyndy Ishida File);
1019a0666956SCyndy Ishida std::vector<UUIDv4> EmptyUUID;
10200116d04dSCyndy Ishida IO.mapTag("!tapi-tbd", true);
10210116d04dSCyndy Ishida IO.mapRequired("tbd-version", Keys->TBDVersion);
10220116d04dSCyndy Ishida IO.mapRequired("targets", Keys->Targets);
1023a0666956SCyndy Ishida IO.mapOptional("uuids", EmptyUUID);
10240116d04dSCyndy Ishida IO.mapOptional("flags", Keys->Flags, TBDFlags::None);
10250116d04dSCyndy Ishida IO.mapRequired("install-name", Keys->InstallName);
10260116d04dSCyndy Ishida IO.mapOptional("current-version", Keys->CurrentVersion,
10270116d04dSCyndy Ishida PackedVersion(1, 0, 0));
10280116d04dSCyndy Ishida IO.mapOptional("compatibility-version", Keys->CompatibilityVersion,
10290116d04dSCyndy Ishida PackedVersion(1, 0, 0));
10300116d04dSCyndy Ishida IO.mapOptional("swift-abi-version", Keys->SwiftABIVersion, SwiftVersion(0));
10310116d04dSCyndy Ishida IO.mapOptional("parent-umbrella", Keys->ParentUmbrellas);
10320116d04dSCyndy Ishida auto OptionKind = MetadataSection::Option::Clients;
10330116d04dSCyndy Ishida IO.mapOptionalWithContext("allowable-clients", Keys->AllowableClients,
10340116d04dSCyndy Ishida OptionKind);
10350116d04dSCyndy Ishida OptionKind = MetadataSection::Option::Libraries;
10360116d04dSCyndy Ishida IO.mapOptionalWithContext("reexported-libraries", Keys->ReexportedLibraries,
10370116d04dSCyndy Ishida OptionKind);
10380116d04dSCyndy Ishida IO.mapOptional("exports", Keys->Exports);
10390116d04dSCyndy Ishida IO.mapOptional("reexports", Keys->Reexports);
10400116d04dSCyndy Ishida IO.mapOptional("undefineds", Keys->Undefineds);
10410116d04dSCyndy Ishida }
10420116d04dSCyndy Ishida };
10430116d04dSCyndy Ishida
10440116d04dSCyndy Ishida template <>
10450116d04dSCyndy Ishida struct DocumentListTraits<std::vector<const MachO::InterfaceFile *>> {
sizellvm::yaml::DocumentListTraits10460116d04dSCyndy Ishida static size_t size(IO &IO, std::vector<const MachO::InterfaceFile *> &Seq) {
10470116d04dSCyndy Ishida return Seq.size();
10480116d04dSCyndy Ishida }
10490116d04dSCyndy Ishida static const InterfaceFile *&
elementllvm::yaml::DocumentListTraits10500116d04dSCyndy Ishida element(IO &IO, std::vector<const InterfaceFile *> &Seq, size_t Index) {
10510116d04dSCyndy Ishida if (Index >= Seq.size())
10520116d04dSCyndy Ishida Seq.resize(Index + 1);
10530116d04dSCyndy Ishida return Seq[Index];
10540116d04dSCyndy Ishida }
10550116d04dSCyndy Ishida };
10560116d04dSCyndy Ishida
10570116d04dSCyndy Ishida } // end namespace yaml.
10580116d04dSCyndy Ishida } // namespace llvm
10590116d04dSCyndy Ishida
DiagHandler(const SMDiagnostic & Diag,void * Context)10600116d04dSCyndy Ishida static void DiagHandler(const SMDiagnostic &Diag, void *Context) {
10610116d04dSCyndy Ishida auto *File = static_cast<TextAPIContext *>(Context);
10620116d04dSCyndy Ishida SmallString<1024> Message;
10630116d04dSCyndy Ishida raw_svector_ostream S(Message);
10640116d04dSCyndy Ishida
10650116d04dSCyndy Ishida SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), File->Path,
10660116d04dSCyndy Ishida Diag.getLineNo(), Diag.getColumnNo(), Diag.getKind(),
10670116d04dSCyndy Ishida Diag.getMessage(), Diag.getLineContents(),
10680116d04dSCyndy Ishida Diag.getRanges(), Diag.getFixIts());
10690116d04dSCyndy Ishida
10700116d04dSCyndy Ishida NewDiag.print(nullptr, S);
10710116d04dSCyndy Ishida File->ErrorMessage = ("malformed file\n" + Message).str();
10720116d04dSCyndy Ishida }
10730116d04dSCyndy Ishida
canRead(MemoryBufferRef InputBuffer)1074455bf3d1SCyndy Ishida Expected<FileType> TextAPIReader::canRead(MemoryBufferRef InputBuffer) {
107579320a0cSCyndy Ishida auto TAPIFile = InputBuffer.getBuffer().trim();
1076586ecdf2SKazu Hirata if (TAPIFile.starts_with("{") && TAPIFile.ends_with("}"))
107779320a0cSCyndy Ishida return FileType::TBD_V5;
107879320a0cSCyndy Ishida
1079586ecdf2SKazu Hirata if (!TAPIFile.ends_with("..."))
108079320a0cSCyndy Ishida return createStringError(std::errc::not_supported, "unsupported file type");
108179320a0cSCyndy Ishida
1082c51095f5SCyndy Ishida if (TAPIFile.starts_with("--- !tapi-tbd"))
108379320a0cSCyndy Ishida return FileType::TBD_V4;
108479320a0cSCyndy Ishida
1085c51095f5SCyndy Ishida if (TAPIFile.starts_with("--- !tapi-tbd-v3"))
108679320a0cSCyndy Ishida return FileType::TBD_V3;
108779320a0cSCyndy Ishida
1088c51095f5SCyndy Ishida if (TAPIFile.starts_with("--- !tapi-tbd-v2"))
108979320a0cSCyndy Ishida return FileType::TBD_V2;
109079320a0cSCyndy Ishida
1091c51095f5SCyndy Ishida if (TAPIFile.starts_with("--- !tapi-tbd-v1") ||
1092586ecdf2SKazu Hirata TAPIFile.starts_with("---\narchs:"))
109379320a0cSCyndy Ishida return FileType::TBD_V1;
109479320a0cSCyndy Ishida
109579320a0cSCyndy Ishida return createStringError(std::errc::not_supported, "unsupported file type");
109679320a0cSCyndy Ishida }
109779320a0cSCyndy Ishida
10980116d04dSCyndy Ishida Expected<std::unique_ptr<InterfaceFile>>
get(MemoryBufferRef InputBuffer)10990116d04dSCyndy Ishida TextAPIReader::get(MemoryBufferRef InputBuffer) {
11000116d04dSCyndy Ishida TextAPIContext Ctx;
11010116d04dSCyndy Ishida Ctx.Path = std::string(InputBuffer.getBufferIdentifier());
1102455bf3d1SCyndy Ishida if (auto FTOrErr = canRead(InputBuffer))
110379320a0cSCyndy Ishida Ctx.FileKind = *FTOrErr;
110479320a0cSCyndy Ishida else
110579320a0cSCyndy Ishida return FTOrErr.takeError();
110679320a0cSCyndy Ishida
110779320a0cSCyndy Ishida // Handle JSON Format.
110879320a0cSCyndy Ishida if (Ctx.FileKind >= FileType::TBD_V5) {
110979320a0cSCyndy Ishida auto FileOrErr = getInterfaceFileFromJSON(InputBuffer.getBuffer());
111079320a0cSCyndy Ishida if (!FileOrErr)
111179320a0cSCyndy Ishida return FileOrErr.takeError();
11121a0d6992SCyndy Ishida
11131a0d6992SCyndy Ishida (*FileOrErr)->setPath(Ctx.Path);
111479320a0cSCyndy Ishida return std::move(*FileOrErr);
111579320a0cSCyndy Ishida }
11160116d04dSCyndy Ishida yaml::Input YAMLIn(InputBuffer.getBuffer(), &Ctx, DiagHandler, &Ctx);
11170116d04dSCyndy Ishida
11180116d04dSCyndy Ishida // Fill vector with interface file objects created by parsing the YAML file.
11190116d04dSCyndy Ishida std::vector<const InterfaceFile *> Files;
11200116d04dSCyndy Ishida YAMLIn >> Files;
11210116d04dSCyndy Ishida
11220116d04dSCyndy Ishida // YAMLIn dynamically allocates for Interface file and in case of error,
11230116d04dSCyndy Ishida // memory leak will occur unless wrapped around unique_ptr
11240116d04dSCyndy Ishida auto File = std::unique_ptr<InterfaceFile>(
11250116d04dSCyndy Ishida const_cast<InterfaceFile *>(Files.front()));
11260116d04dSCyndy Ishida
1127cfc74024SKazu Hirata for (const InterfaceFile *FI : llvm::drop_begin(Files))
11280116d04dSCyndy Ishida File->addDocument(
1129cfc74024SKazu Hirata std::shared_ptr<InterfaceFile>(const_cast<InterfaceFile *>(FI)));
11300116d04dSCyndy Ishida
11310116d04dSCyndy Ishida if (YAMLIn.error())
11320116d04dSCyndy Ishida return make_error<StringError>(Ctx.ErrorMessage, YAMLIn.error());
11330116d04dSCyndy Ishida
11340116d04dSCyndy Ishida return std::move(File);
11350116d04dSCyndy Ishida }
11360116d04dSCyndy Ishida
writeToStream(raw_ostream & OS,const InterfaceFile & File,const FileType FileKind,bool Compact)1137d6f9b97bSCyndy Ishida Error TextAPIWriter::writeToStream(raw_ostream &OS, const InterfaceFile &File,
1138455bf3d1SCyndy Ishida const FileType FileKind, bool Compact) {
11390116d04dSCyndy Ishida TextAPIContext Ctx;
11400116d04dSCyndy Ishida Ctx.Path = std::string(File.getPath());
1141455bf3d1SCyndy Ishida
1142455bf3d1SCyndy Ishida // Prefer parameter for format if passed, otherwise fallback to the File
1143455bf3d1SCyndy Ishida // FileType.
1144455bf3d1SCyndy Ishida Ctx.FileKind =
1145455bf3d1SCyndy Ishida (FileKind == FileType::Invalid) ? File.getFileType() : FileKind;
1146d6f9b97bSCyndy Ishida
1147d6f9b97bSCyndy Ishida // Write out in JSON format.
1148d6f9b97bSCyndy Ishida if (Ctx.FileKind >= FileType::TBD_V5) {
1149455bf3d1SCyndy Ishida return serializeInterfaceFileToJSON(OS, File, Ctx.FileKind, Compact);
1150d6f9b97bSCyndy Ishida }
1151d6f9b97bSCyndy Ishida
11520116d04dSCyndy Ishida llvm::yaml::Output YAMLOut(OS, &Ctx, /*WrapColumn=*/80);
11530116d04dSCyndy Ishida
11540116d04dSCyndy Ishida std::vector<const InterfaceFile *> Files;
11550116d04dSCyndy Ishida Files.emplace_back(&File);
11560116d04dSCyndy Ishida
115740dc8e68SGregory Alfonso for (const auto &Document : File.documents())
11580116d04dSCyndy Ishida Files.emplace_back(Document.get());
11590116d04dSCyndy Ishida
11600116d04dSCyndy Ishida // Stream out yaml.
11610116d04dSCyndy Ishida YAMLOut << Files;
11620116d04dSCyndy Ishida
11630116d04dSCyndy Ishida return Error::success();
11640116d04dSCyndy Ishida }
1165