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; 2580116d04dSCyndy 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> { 2870116d04dSCyndy 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> { 3090116d04dSCyndy 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> { 3250116d04dSCyndy 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> { 3370116d04dSCyndy 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> { 3440116d04dSCyndy 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> { 3520116d04dSCyndy 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> { 3680116d04dSCyndy 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> { 3770116d04dSCyndy 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; 3830116d04dSCyndy Ishida case PlatformKind::macOS: 3840116d04dSCyndy Ishida OS << "macos"; 3850116d04dSCyndy Ishida break; 3860116d04dSCyndy Ishida case PlatformKind::iOS: 3870116d04dSCyndy Ishida OS << "ios"; 3880116d04dSCyndy Ishida break; 3890116d04dSCyndy Ishida case PlatformKind::tvOS: 3900116d04dSCyndy Ishida OS << "tvos"; 3910116d04dSCyndy Ishida break; 3920116d04dSCyndy Ishida case PlatformKind::watchOS: 3930116d04dSCyndy Ishida OS << "watchos"; 3940116d04dSCyndy Ishida break; 3950116d04dSCyndy Ishida case PlatformKind::bridgeOS: 3960116d04dSCyndy Ishida OS << "bridgeos"; 3970116d04dSCyndy Ishida break; 3980116d04dSCyndy Ishida case PlatformKind::macCatalyst: 3990116d04dSCyndy Ishida OS << "maccatalyst"; 4000116d04dSCyndy Ishida break; 4010116d04dSCyndy Ishida case PlatformKind::iOSSimulator: 4020116d04dSCyndy Ishida OS << "ios-simulator"; 4030116d04dSCyndy Ishida break; 4040116d04dSCyndy Ishida case PlatformKind::tvOSSimulator: 4050116d04dSCyndy Ishida OS << "tvos-simulator"; 4060116d04dSCyndy Ishida break; 4070116d04dSCyndy Ishida case PlatformKind::watchOSSimulator: 4080116d04dSCyndy Ishida OS << "watchos-simulator"; 4090116d04dSCyndy Ishida break; 4100116d04dSCyndy Ishida case PlatformKind::driverKit: 4110116d04dSCyndy Ishida OS << "driverkit"; 4120116d04dSCyndy Ishida break; 4130116d04dSCyndy Ishida } 4140116d04dSCyndy Ishida } 4150116d04dSCyndy Ishida 4160116d04dSCyndy 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"; 4260116d04dSCyndy Ishida if (Value.Platform == PlatformKind::unknown) 4270116d04dSCyndy Ishida return "unknown platform"; 4280116d04dSCyndy Ishida 4290116d04dSCyndy Ishida return {}; 4300116d04dSCyndy Ishida } 4310116d04dSCyndy Ishida 4320116d04dSCyndy Ishida static QuotingType mustQuote(StringRef) { return QuotingType::None; } 4330116d04dSCyndy Ishida }; 4340116d04dSCyndy Ishida 4350116d04dSCyndy Ishida template <> struct MappingTraits<const InterfaceFile *> { 4360116d04dSCyndy Ishida struct NormalizedTBD { 4370116d04dSCyndy Ishida explicit NormalizedTBD(IO &IO) {} 4380116d04dSCyndy 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. 5950116d04dSCyndy Ishida TargetList synthesizeTargets(ArchitectureSet Architectures, 5960116d04dSCyndy Ishida const PlatformSet &Platforms) { 5970116d04dSCyndy Ishida TargetList Targets; 5980116d04dSCyndy Ishida 5990116d04dSCyndy Ishida for (auto Platform : Platforms) { 6000116d04dSCyndy Ishida Platform = mapToPlatformKind(Platform, Architectures.hasX86()); 6010116d04dSCyndy Ishida 6020116d04dSCyndy Ishida for (const auto &&Architecture : Architectures) { 6030116d04dSCyndy Ishida if ((Architecture == AK_i386) && 6040116d04dSCyndy Ishida (Platform == PlatformKind::macCatalyst)) 6050116d04dSCyndy Ishida continue; 6060116d04dSCyndy Ishida 6070116d04dSCyndy Ishida Targets.emplace_back(Architecture, Platform); 6080116d04dSCyndy Ishida } 6090116d04dSCyndy Ishida } 6100116d04dSCyndy Ishida return Targets; 6110116d04dSCyndy Ishida } 6120116d04dSCyndy Ishida 6130116d04dSCyndy Ishida const InterfaceFile *denormalize(IO &IO) { 6140116d04dSCyndy Ishida auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext()); 6150116d04dSCyndy Ishida assert(Ctx); 6160116d04dSCyndy Ishida 6170116d04dSCyndy Ishida auto *File = new InterfaceFile; 6180116d04dSCyndy Ishida File->setPath(Ctx->Path); 6190116d04dSCyndy Ishida File->setFileType(Ctx->FileKind); 6200116d04dSCyndy Ishida File->addTargets(synthesizeTargets(Architectures, Platforms)); 6210116d04dSCyndy Ishida for (auto &ID : UUIDs) 6220116d04dSCyndy Ishida File->addUUID(ID.first, ID.second); 6230116d04dSCyndy Ishida File->setInstallName(InstallName); 6240116d04dSCyndy Ishida File->setCurrentVersion(CurrentVersion); 6250116d04dSCyndy Ishida File->setCompatibilityVersion(CompatibilityVersion); 6260116d04dSCyndy Ishida File->setSwiftABIVersion(SwiftABIVersion); 6270116d04dSCyndy Ishida File->setObjCConstraint(ObjCConstraint); 6280116d04dSCyndy Ishida for (const auto &Target : File->targets()) 6290116d04dSCyndy Ishida File->addParentUmbrella(Target, ParentUmbrella); 6300116d04dSCyndy Ishida 6310116d04dSCyndy Ishida if (Ctx->FileKind == FileType::TBD_V1) { 6320116d04dSCyndy Ishida File->setTwoLevelNamespace(); 6330116d04dSCyndy Ishida File->setApplicationExtensionSafe(); 6340116d04dSCyndy Ishida } else { 6350116d04dSCyndy Ishida File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace)); 6360116d04dSCyndy Ishida File->setApplicationExtensionSafe( 6370116d04dSCyndy Ishida !(Flags & TBDFlags::NotApplicationExtensionSafe)); 6380116d04dSCyndy Ishida File->setInstallAPI(Flags & TBDFlags::InstallAPI); 6390116d04dSCyndy Ishida } 6400116d04dSCyndy Ishida 6410116d04dSCyndy Ishida for (const auto &Section : Exports) { 6420116d04dSCyndy Ishida const auto Targets = 6430116d04dSCyndy Ishida synthesizeTargets(Section.Architectures, Platforms); 6440116d04dSCyndy Ishida 6450116d04dSCyndy Ishida for (const auto &Lib : Section.AllowableClients) 6460116d04dSCyndy Ishida for (const auto &Target : Targets) 6470116d04dSCyndy Ishida File->addAllowableClient(Lib, Target); 6480116d04dSCyndy Ishida 6490116d04dSCyndy Ishida for (const auto &Lib : Section.ReexportedLibraries) 6500116d04dSCyndy Ishida for (const auto &Target : Targets) 6510116d04dSCyndy Ishida File->addReexportedLibrary(Lib, Target); 6520116d04dSCyndy Ishida 6530116d04dSCyndy Ishida for (const auto &Symbol : Section.Symbols) { 6540116d04dSCyndy Ishida if (Ctx->FileKind != FileType::TBD_V3 && 6550116d04dSCyndy Ishida Symbol.value.startswith("_OBJC_EHTYPE_$_")) 6560116d04dSCyndy Ishida File->addSymbol(SymbolKind::ObjectiveCClassEHType, 6570116d04dSCyndy Ishida Symbol.value.drop_front(15), Targets); 6580116d04dSCyndy Ishida else 6590116d04dSCyndy Ishida File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets); 6600116d04dSCyndy Ishida } 6610116d04dSCyndy Ishida for (auto &Symbol : Section.Classes) { 6620116d04dSCyndy Ishida auto Name = Symbol.value; 6630116d04dSCyndy Ishida if (Ctx->FileKind != FileType::TBD_V3) 6640116d04dSCyndy Ishida Name = Name.drop_front(); 6650116d04dSCyndy Ishida File->addSymbol(SymbolKind::ObjectiveCClass, Name, Targets); 6660116d04dSCyndy Ishida } 6670116d04dSCyndy Ishida for (auto &Symbol : Section.ClassEHs) 6680116d04dSCyndy Ishida File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol, Targets); 6690116d04dSCyndy Ishida for (auto &Symbol : Section.IVars) { 6700116d04dSCyndy Ishida auto Name = Symbol.value; 6710116d04dSCyndy Ishida if (Ctx->FileKind != FileType::TBD_V3) 6720116d04dSCyndy Ishida Name = Name.drop_front(); 6730116d04dSCyndy Ishida File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name, 6740116d04dSCyndy Ishida Targets); 6750116d04dSCyndy Ishida } 6760116d04dSCyndy Ishida for (auto &Symbol : Section.WeakDefSymbols) 6770116d04dSCyndy Ishida File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets, 6780116d04dSCyndy Ishida SymbolFlags::WeakDefined); 6790116d04dSCyndy Ishida for (auto &Symbol : Section.TLVSymbols) 6800116d04dSCyndy Ishida File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets, 6810116d04dSCyndy Ishida SymbolFlags::ThreadLocalValue); 6820116d04dSCyndy Ishida } 6830116d04dSCyndy Ishida 6840116d04dSCyndy Ishida for (const auto &Section : Undefineds) { 6850116d04dSCyndy Ishida const auto Targets = 6860116d04dSCyndy Ishida synthesizeTargets(Section.Architectures, Platforms); 6870116d04dSCyndy Ishida for (auto &Symbol : Section.Symbols) { 6880116d04dSCyndy Ishida if (Ctx->FileKind != FileType::TBD_V3 && 6890116d04dSCyndy Ishida Symbol.value.startswith("_OBJC_EHTYPE_$_")) 6900116d04dSCyndy Ishida File->addSymbol(SymbolKind::ObjectiveCClassEHType, 6910116d04dSCyndy Ishida Symbol.value.drop_front(15), Targets, 6920116d04dSCyndy Ishida SymbolFlags::Undefined); 6930116d04dSCyndy Ishida else 6940116d04dSCyndy Ishida File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets, 6950116d04dSCyndy Ishida SymbolFlags::Undefined); 6960116d04dSCyndy Ishida } 6970116d04dSCyndy Ishida for (auto &Symbol : Section.Classes) { 6980116d04dSCyndy Ishida auto Name = Symbol.value; 6990116d04dSCyndy Ishida if (Ctx->FileKind != FileType::TBD_V3) 7000116d04dSCyndy Ishida Name = Name.drop_front(); 7010116d04dSCyndy Ishida File->addSymbol(SymbolKind::ObjectiveCClass, Name, Targets, 7020116d04dSCyndy Ishida SymbolFlags::Undefined); 7030116d04dSCyndy Ishida } 7040116d04dSCyndy Ishida for (auto &Symbol : Section.ClassEHs) 7050116d04dSCyndy Ishida File->addSymbol(SymbolKind::ObjectiveCClassEHType, Symbol, Targets, 7060116d04dSCyndy Ishida SymbolFlags::Undefined); 7070116d04dSCyndy Ishida for (auto &Symbol : Section.IVars) { 7080116d04dSCyndy Ishida auto Name = Symbol.value; 7090116d04dSCyndy Ishida if (Ctx->FileKind != FileType::TBD_V3) 7100116d04dSCyndy Ishida Name = Name.drop_front(); 7110116d04dSCyndy Ishida File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, Name, Targets, 7120116d04dSCyndy Ishida SymbolFlags::Undefined); 7130116d04dSCyndy Ishida } 7140116d04dSCyndy Ishida for (auto &Symbol : Section.WeakRefSymbols) 7150116d04dSCyndy Ishida File->addSymbol(SymbolKind::GlobalSymbol, Symbol, Targets, 7160116d04dSCyndy Ishida SymbolFlags::Undefined | SymbolFlags::WeakReferenced); 7170116d04dSCyndy Ishida } 7180116d04dSCyndy Ishida 7190116d04dSCyndy Ishida return File; 7200116d04dSCyndy Ishida } 7210116d04dSCyndy Ishida 7220116d04dSCyndy Ishida llvm::BumpPtrAllocator Allocator; 7230116d04dSCyndy Ishida StringRef copyString(StringRef String) { 7240116d04dSCyndy Ishida if (String.empty()) 7250116d04dSCyndy Ishida return {}; 7260116d04dSCyndy Ishida 7270116d04dSCyndy Ishida void *Ptr = Allocator.Allocate(String.size(), 1); 7280116d04dSCyndy Ishida memcpy(Ptr, String.data(), String.size()); 7290116d04dSCyndy Ishida return StringRef(reinterpret_cast<const char *>(Ptr), String.size()); 7300116d04dSCyndy Ishida } 7310116d04dSCyndy Ishida 7320116d04dSCyndy Ishida std::vector<Architecture> Architectures; 7330116d04dSCyndy Ishida std::vector<UUID> UUIDs; 7340116d04dSCyndy Ishida PlatformSet Platforms; 7350116d04dSCyndy Ishida StringRef InstallName; 7360116d04dSCyndy Ishida PackedVersion CurrentVersion; 7370116d04dSCyndy Ishida PackedVersion CompatibilityVersion; 7380116d04dSCyndy Ishida SwiftVersion SwiftABIVersion{0}; 7390116d04dSCyndy Ishida ObjCConstraintType ObjCConstraint{ObjCConstraintType::None}; 7400116d04dSCyndy Ishida TBDFlags Flags{TBDFlags::None}; 7410116d04dSCyndy Ishida StringRef ParentUmbrella; 7420116d04dSCyndy Ishida std::vector<ExportSection> Exports; 7430116d04dSCyndy Ishida std::vector<UndefinedSection> Undefineds; 7440116d04dSCyndy Ishida }; 7450116d04dSCyndy Ishida 7460116d04dSCyndy Ishida static void setFileTypeForInput(TextAPIContext *Ctx, IO &IO) { 7470116d04dSCyndy Ishida if (IO.mapTag("!tapi-tbd", false)) 7480116d04dSCyndy Ishida Ctx->FileKind = FileType::TBD_V4; 7490116d04dSCyndy Ishida else if (IO.mapTag("!tapi-tbd-v3", false)) 7500116d04dSCyndy Ishida Ctx->FileKind = FileType::TBD_V3; 7510116d04dSCyndy Ishida else if (IO.mapTag("!tapi-tbd-v2", false)) 7520116d04dSCyndy Ishida Ctx->FileKind = FileType::TBD_V2; 7530116d04dSCyndy Ishida else if (IO.mapTag("!tapi-tbd-v1", false) || 7540116d04dSCyndy Ishida IO.mapTag("tag:yaml.org,2002:map", false)) 7550116d04dSCyndy Ishida Ctx->FileKind = FileType::TBD_V1; 7560116d04dSCyndy Ishida else { 7570116d04dSCyndy Ishida Ctx->FileKind = FileType::Invalid; 7580116d04dSCyndy Ishida return; 7590116d04dSCyndy Ishida } 7600116d04dSCyndy Ishida } 7610116d04dSCyndy Ishida 7620116d04dSCyndy Ishida static void mapping(IO &IO, const InterfaceFile *&File) { 7630116d04dSCyndy Ishida auto *Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext()); 7640116d04dSCyndy Ishida assert((!Ctx || !IO.outputting() || 7650116d04dSCyndy Ishida (Ctx && Ctx->FileKind != FileType::Invalid)) && 7660116d04dSCyndy Ishida "File type is not set in YAML context"); 7670116d04dSCyndy Ishida 7680116d04dSCyndy Ishida if (!IO.outputting()) { 7690116d04dSCyndy Ishida setFileTypeForInput(Ctx, IO); 7700116d04dSCyndy Ishida switch (Ctx->FileKind) { 7710116d04dSCyndy Ishida default: 7720116d04dSCyndy Ishida break; 7730116d04dSCyndy Ishida case FileType::TBD_V4: 7740116d04dSCyndy Ishida mapKeysToValuesV4(IO, File); 7750116d04dSCyndy Ishida return; 7760116d04dSCyndy Ishida case FileType::Invalid: 7770116d04dSCyndy Ishida IO.setError("unsupported file type"); 7780116d04dSCyndy Ishida return; 7790116d04dSCyndy Ishida } 7800116d04dSCyndy Ishida } else { 7810116d04dSCyndy Ishida // Set file type when writing. 7820116d04dSCyndy Ishida switch (Ctx->FileKind) { 7830116d04dSCyndy Ishida default: 7840116d04dSCyndy Ishida llvm_unreachable("unexpected file type"); 7850116d04dSCyndy Ishida case FileType::TBD_V4: 7860116d04dSCyndy Ishida mapKeysToValuesV4(IO, File); 7870116d04dSCyndy Ishida return; 7880116d04dSCyndy Ishida case FileType::TBD_V3: 7890116d04dSCyndy Ishida IO.mapTag("!tapi-tbd-v3", true); 7900116d04dSCyndy Ishida break; 7910116d04dSCyndy Ishida case FileType::TBD_V2: 7920116d04dSCyndy Ishida IO.mapTag("!tapi-tbd-v2", true); 7930116d04dSCyndy Ishida break; 7940116d04dSCyndy Ishida case FileType::TBD_V1: 7950116d04dSCyndy Ishida // Don't write the tag into the .tbd file for TBD v1 7960116d04dSCyndy Ishida break; 7970116d04dSCyndy Ishida } 7980116d04dSCyndy Ishida } 7990116d04dSCyndy Ishida mapKeysToValues(Ctx->FileKind, IO, File); 8000116d04dSCyndy Ishida } 8010116d04dSCyndy Ishida 8020116d04dSCyndy Ishida using SectionList = std::vector<SymbolSection>; 8030116d04dSCyndy Ishida struct NormalizedTBD_V4 { 8040116d04dSCyndy Ishida explicit NormalizedTBD_V4(IO &IO) {} 8050116d04dSCyndy Ishida NormalizedTBD_V4(IO &IO, const InterfaceFile *&File) { 8060116d04dSCyndy Ishida auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext()); 8070116d04dSCyndy Ishida assert(Ctx); 8080116d04dSCyndy Ishida TBDVersion = Ctx->FileKind >> 1; 8090116d04dSCyndy Ishida Targets.insert(Targets.begin(), File->targets().begin(), 8100116d04dSCyndy Ishida File->targets().end()); 8110116d04dSCyndy Ishida for (const auto &IT : File->uuids()) 8120116d04dSCyndy Ishida UUIDs.emplace_back(IT.first, IT.second); 8130116d04dSCyndy Ishida InstallName = File->getInstallName(); 8140116d04dSCyndy Ishida CurrentVersion = File->getCurrentVersion(); 8150116d04dSCyndy Ishida CompatibilityVersion = File->getCompatibilityVersion(); 8160116d04dSCyndy Ishida SwiftABIVersion = File->getSwiftABIVersion(); 8170116d04dSCyndy Ishida 8180116d04dSCyndy Ishida Flags = TBDFlags::None; 8190116d04dSCyndy Ishida if (!File->isApplicationExtensionSafe()) 8200116d04dSCyndy Ishida Flags |= TBDFlags::NotApplicationExtensionSafe; 8210116d04dSCyndy Ishida 8220116d04dSCyndy Ishida if (!File->isTwoLevelNamespace()) 8230116d04dSCyndy Ishida Flags |= TBDFlags::FlatNamespace; 8240116d04dSCyndy Ishida 8250116d04dSCyndy Ishida if (File->isInstallAPI()) 8260116d04dSCyndy Ishida Flags |= TBDFlags::InstallAPI; 8270116d04dSCyndy Ishida 8280116d04dSCyndy Ishida { 8290116d04dSCyndy Ishida std::map<std::string, TargetList> valueToTargetList; 8300116d04dSCyndy Ishida for (const auto &it : File->umbrellas()) 8310116d04dSCyndy Ishida valueToTargetList[it.second].emplace_back(it.first); 8320116d04dSCyndy Ishida 8330116d04dSCyndy Ishida for (const auto &it : valueToTargetList) { 8340116d04dSCyndy Ishida UmbrellaSection CurrentSection; 8350116d04dSCyndy Ishida CurrentSection.Targets.insert(CurrentSection.Targets.begin(), 8360116d04dSCyndy Ishida it.second.begin(), it.second.end()); 8370116d04dSCyndy Ishida CurrentSection.Umbrella = it.first; 8380116d04dSCyndy Ishida ParentUmbrellas.emplace_back(std::move(CurrentSection)); 8390116d04dSCyndy Ishida } 8400116d04dSCyndy Ishida } 8410116d04dSCyndy Ishida 8420116d04dSCyndy Ishida assignTargetsToLibrary(File->allowableClients(), AllowableClients); 8430116d04dSCyndy Ishida assignTargetsToLibrary(File->reexportedLibraries(), ReexportedLibraries); 8440116d04dSCyndy Ishida 8450116d04dSCyndy Ishida auto handleSymbols = 8460116d04dSCyndy Ishida [](SectionList &CurrentSections, 8470116d04dSCyndy Ishida InterfaceFile::const_filtered_symbol_range Symbols, 8480116d04dSCyndy Ishida std::function<bool(const Symbol *)> Pred) { 8490116d04dSCyndy Ishida std::set<TargetList> TargetSet; 8500116d04dSCyndy Ishida std::map<const Symbol *, TargetList> SymbolToTargetList; 8510116d04dSCyndy Ishida for (const auto *Symbol : Symbols) { 8520116d04dSCyndy Ishida if (!Pred(Symbol)) 8530116d04dSCyndy Ishida continue; 8540116d04dSCyndy Ishida TargetList Targets(Symbol->targets()); 8550116d04dSCyndy Ishida SymbolToTargetList[Symbol] = Targets; 8560116d04dSCyndy Ishida TargetSet.emplace(std::move(Targets)); 8570116d04dSCyndy Ishida } 8580116d04dSCyndy Ishida for (const auto &TargetIDs : TargetSet) { 8590116d04dSCyndy Ishida SymbolSection CurrentSection; 8600116d04dSCyndy Ishida CurrentSection.Targets.insert(CurrentSection.Targets.begin(), 8610116d04dSCyndy Ishida TargetIDs.begin(), TargetIDs.end()); 8620116d04dSCyndy Ishida 8630116d04dSCyndy Ishida for (const auto &IT : SymbolToTargetList) { 8640116d04dSCyndy Ishida if (IT.second != TargetIDs) 8650116d04dSCyndy Ishida continue; 8660116d04dSCyndy Ishida 8670116d04dSCyndy Ishida const auto *Symbol = IT.first; 8680116d04dSCyndy Ishida switch (Symbol->getKind()) { 8690116d04dSCyndy Ishida case SymbolKind::GlobalSymbol: 8700116d04dSCyndy Ishida if (Symbol->isWeakDefined()) 8710116d04dSCyndy Ishida CurrentSection.WeakSymbols.emplace_back(Symbol->getName()); 8720116d04dSCyndy Ishida else if (Symbol->isThreadLocalValue()) 8730116d04dSCyndy Ishida CurrentSection.TlvSymbols.emplace_back(Symbol->getName()); 8740116d04dSCyndy Ishida else 8750116d04dSCyndy Ishida CurrentSection.Symbols.emplace_back(Symbol->getName()); 8760116d04dSCyndy Ishida break; 8770116d04dSCyndy Ishida case SymbolKind::ObjectiveCClass: 8780116d04dSCyndy Ishida CurrentSection.Classes.emplace_back(Symbol->getName()); 8790116d04dSCyndy Ishida break; 8800116d04dSCyndy Ishida case SymbolKind::ObjectiveCClassEHType: 8810116d04dSCyndy Ishida CurrentSection.ClassEHs.emplace_back(Symbol->getName()); 8820116d04dSCyndy Ishida break; 8830116d04dSCyndy Ishida case SymbolKind::ObjectiveCInstanceVariable: 8840116d04dSCyndy Ishida CurrentSection.Ivars.emplace_back(Symbol->getName()); 8850116d04dSCyndy Ishida break; 8860116d04dSCyndy Ishida } 8870116d04dSCyndy Ishida } 8880116d04dSCyndy Ishida sort(CurrentSection.Symbols); 8890116d04dSCyndy Ishida sort(CurrentSection.Classes); 8900116d04dSCyndy Ishida sort(CurrentSection.ClassEHs); 8910116d04dSCyndy Ishida sort(CurrentSection.Ivars); 8920116d04dSCyndy Ishida sort(CurrentSection.WeakSymbols); 8930116d04dSCyndy Ishida sort(CurrentSection.TlvSymbols); 8940116d04dSCyndy Ishida CurrentSections.emplace_back(std::move(CurrentSection)); 8950116d04dSCyndy Ishida } 8960116d04dSCyndy Ishida }; 8970116d04dSCyndy Ishida 8980116d04dSCyndy Ishida handleSymbols(Exports, File->exports(), [](const Symbol *Symbol) { 8990116d04dSCyndy Ishida return !Symbol->isReexported(); 9000116d04dSCyndy Ishida }); 9010116d04dSCyndy Ishida handleSymbols(Reexports, File->exports(), [](const Symbol *Symbol) { 9020116d04dSCyndy Ishida return Symbol->isReexported(); 9030116d04dSCyndy Ishida }); 9040116d04dSCyndy Ishida handleSymbols(Undefineds, File->undefineds(), 9050116d04dSCyndy Ishida [](const Symbol *Symbol) { return true; }); 9060116d04dSCyndy Ishida } 9070116d04dSCyndy Ishida 9080116d04dSCyndy Ishida const InterfaceFile *denormalize(IO &IO) { 9090116d04dSCyndy Ishida auto Ctx = reinterpret_cast<TextAPIContext *>(IO.getContext()); 9100116d04dSCyndy Ishida assert(Ctx); 9110116d04dSCyndy Ishida 9120116d04dSCyndy Ishida auto *File = new InterfaceFile; 9130116d04dSCyndy Ishida File->setPath(Ctx->Path); 9140116d04dSCyndy Ishida File->setFileType(Ctx->FileKind); 9150116d04dSCyndy Ishida for (auto &id : UUIDs) 9160116d04dSCyndy Ishida File->addUUID(id.TargetID, id.Value); 9170116d04dSCyndy Ishida File->addTargets(Targets); 9180116d04dSCyndy Ishida File->setInstallName(InstallName); 9190116d04dSCyndy Ishida File->setCurrentVersion(CurrentVersion); 9200116d04dSCyndy Ishida File->setCompatibilityVersion(CompatibilityVersion); 9210116d04dSCyndy Ishida File->setSwiftABIVersion(SwiftABIVersion); 9220116d04dSCyndy Ishida for (const auto &CurrentSection : ParentUmbrellas) 9230116d04dSCyndy Ishida for (const auto &target : CurrentSection.Targets) 9240116d04dSCyndy Ishida File->addParentUmbrella(target, CurrentSection.Umbrella); 9250116d04dSCyndy Ishida File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace)); 9260116d04dSCyndy Ishida File->setApplicationExtensionSafe( 9270116d04dSCyndy Ishida !(Flags & TBDFlags::NotApplicationExtensionSafe)); 9280116d04dSCyndy Ishida File->setInstallAPI(Flags & TBDFlags::InstallAPI); 9290116d04dSCyndy Ishida 9300116d04dSCyndy Ishida for (const auto &CurrentSection : AllowableClients) { 9310116d04dSCyndy Ishida for (const auto &lib : CurrentSection.Values) 9320116d04dSCyndy Ishida for (const auto &Target : CurrentSection.Targets) 9330116d04dSCyndy Ishida File->addAllowableClient(lib, Target); 9340116d04dSCyndy Ishida } 9350116d04dSCyndy Ishida 9360116d04dSCyndy Ishida for (const auto &CurrentSection : ReexportedLibraries) { 9370116d04dSCyndy Ishida for (const auto &Lib : CurrentSection.Values) 9380116d04dSCyndy Ishida for (const auto &Target : CurrentSection.Targets) 9390116d04dSCyndy Ishida File->addReexportedLibrary(Lib, Target); 9400116d04dSCyndy Ishida } 9410116d04dSCyndy Ishida 9420116d04dSCyndy Ishida auto handleSymbols = [File](const SectionList &CurrentSections, 9430116d04dSCyndy Ishida SymbolFlags Flag = SymbolFlags::None) { 9440116d04dSCyndy Ishida for (const auto &CurrentSection : CurrentSections) { 9450116d04dSCyndy Ishida for (auto &sym : CurrentSection.Symbols) 9460116d04dSCyndy Ishida File->addSymbol(SymbolKind::GlobalSymbol, sym, 9470116d04dSCyndy Ishida CurrentSection.Targets, Flag); 9480116d04dSCyndy Ishida 9490116d04dSCyndy Ishida for (auto &sym : CurrentSection.Classes) 9500116d04dSCyndy Ishida File->addSymbol(SymbolKind::ObjectiveCClass, sym, 9510116d04dSCyndy Ishida CurrentSection.Targets); 9520116d04dSCyndy Ishida 9530116d04dSCyndy Ishida for (auto &sym : CurrentSection.ClassEHs) 9540116d04dSCyndy Ishida File->addSymbol(SymbolKind::ObjectiveCClassEHType, sym, 9550116d04dSCyndy Ishida CurrentSection.Targets); 9560116d04dSCyndy Ishida 9570116d04dSCyndy Ishida for (auto &sym : CurrentSection.Ivars) 9580116d04dSCyndy Ishida File->addSymbol(SymbolKind::ObjectiveCInstanceVariable, sym, 9590116d04dSCyndy Ishida CurrentSection.Targets); 9600116d04dSCyndy Ishida 9610116d04dSCyndy Ishida for (auto &sym : CurrentSection.WeakSymbols) 9620116d04dSCyndy Ishida File->addSymbol(SymbolKind::GlobalSymbol, sym, 9630116d04dSCyndy Ishida CurrentSection.Targets, SymbolFlags::WeakDefined); 9640116d04dSCyndy Ishida 9650116d04dSCyndy Ishida for (auto &sym : CurrentSection.TlvSymbols) 9660116d04dSCyndy Ishida File->addSymbol(SymbolKind::GlobalSymbol, sym, 9670116d04dSCyndy Ishida CurrentSection.Targets, 9680116d04dSCyndy Ishida SymbolFlags::ThreadLocalValue); 9690116d04dSCyndy Ishida } 9700116d04dSCyndy Ishida }; 9710116d04dSCyndy Ishida 9720116d04dSCyndy Ishida handleSymbols(Exports); 9730116d04dSCyndy Ishida handleSymbols(Reexports, SymbolFlags::Rexported); 9740116d04dSCyndy Ishida handleSymbols(Undefineds, SymbolFlags::Undefined); 9750116d04dSCyndy Ishida 9760116d04dSCyndy Ishida return File; 9770116d04dSCyndy Ishida } 9780116d04dSCyndy Ishida 9790116d04dSCyndy Ishida unsigned TBDVersion; 9800116d04dSCyndy Ishida std::vector<UUIDv4> UUIDs; 9810116d04dSCyndy Ishida TargetList Targets; 9820116d04dSCyndy Ishida StringRef InstallName; 9830116d04dSCyndy Ishida PackedVersion CurrentVersion; 9840116d04dSCyndy Ishida PackedVersion CompatibilityVersion; 9850116d04dSCyndy Ishida SwiftVersion SwiftABIVersion{0}; 9860116d04dSCyndy Ishida std::vector<MetadataSection> AllowableClients; 9870116d04dSCyndy Ishida std::vector<MetadataSection> ReexportedLibraries; 9880116d04dSCyndy Ishida TBDFlags Flags{TBDFlags::None}; 9890116d04dSCyndy Ishida std::vector<UmbrellaSection> ParentUmbrellas; 9900116d04dSCyndy Ishida SectionList Exports; 9910116d04dSCyndy Ishida SectionList Reexports; 9920116d04dSCyndy Ishida SectionList Undefineds; 9930116d04dSCyndy Ishida 9940116d04dSCyndy Ishida private: 9950116d04dSCyndy Ishida void assignTargetsToLibrary(const std::vector<InterfaceFileRef> &Libraries, 9960116d04dSCyndy Ishida std::vector<MetadataSection> &Section) { 9970116d04dSCyndy Ishida std::set<TargetList> targetSet; 9980116d04dSCyndy Ishida std::map<const InterfaceFileRef *, TargetList> valueToTargetList; 9990116d04dSCyndy Ishida for (const auto &library : Libraries) { 10000116d04dSCyndy Ishida TargetList targets(library.targets()); 10010116d04dSCyndy Ishida valueToTargetList[&library] = targets; 10020116d04dSCyndy Ishida targetSet.emplace(std::move(targets)); 10030116d04dSCyndy Ishida } 10040116d04dSCyndy Ishida 10050116d04dSCyndy Ishida for (const auto &targets : targetSet) { 10060116d04dSCyndy Ishida MetadataSection CurrentSection; 10070116d04dSCyndy Ishida CurrentSection.Targets.insert(CurrentSection.Targets.begin(), 10080116d04dSCyndy Ishida targets.begin(), targets.end()); 10090116d04dSCyndy Ishida 10100116d04dSCyndy Ishida for (const auto &it : valueToTargetList) { 10110116d04dSCyndy Ishida if (it.second != targets) 10120116d04dSCyndy Ishida continue; 10130116d04dSCyndy Ishida 10140116d04dSCyndy Ishida CurrentSection.Values.emplace_back(it.first->getInstallName()); 10150116d04dSCyndy Ishida } 10160116d04dSCyndy Ishida llvm::sort(CurrentSection.Values); 10170116d04dSCyndy Ishida Section.emplace_back(std::move(CurrentSection)); 10180116d04dSCyndy Ishida } 10190116d04dSCyndy Ishida } 10200116d04dSCyndy Ishida }; 10210116d04dSCyndy Ishida 10220116d04dSCyndy Ishida static void mapKeysToValues(FileType FileKind, IO &IO, 10230116d04dSCyndy Ishida const InterfaceFile *&File) { 10240116d04dSCyndy Ishida MappingNormalization<NormalizedTBD, const InterfaceFile *> Keys(IO, File); 10250116d04dSCyndy Ishida IO.mapRequired("archs", Keys->Architectures); 10260116d04dSCyndy Ishida if (FileKind != FileType::TBD_V1) 10270116d04dSCyndy Ishida IO.mapOptional("uuids", Keys->UUIDs); 10280116d04dSCyndy Ishida IO.mapRequired("platform", Keys->Platforms); 10290116d04dSCyndy Ishida if (FileKind != FileType::TBD_V1) 10300116d04dSCyndy Ishida IO.mapOptional("flags", Keys->Flags, TBDFlags::None); 10310116d04dSCyndy Ishida IO.mapRequired("install-name", Keys->InstallName); 10320116d04dSCyndy Ishida IO.mapOptional("current-version", Keys->CurrentVersion, 10330116d04dSCyndy Ishida PackedVersion(1, 0, 0)); 10340116d04dSCyndy Ishida IO.mapOptional("compatibility-version", Keys->CompatibilityVersion, 10350116d04dSCyndy Ishida PackedVersion(1, 0, 0)); 10360116d04dSCyndy Ishida if (FileKind != FileType::TBD_V3) 10370116d04dSCyndy Ishida IO.mapOptional("swift-version", Keys->SwiftABIVersion, SwiftVersion(0)); 10380116d04dSCyndy Ishida else 10390116d04dSCyndy Ishida IO.mapOptional("swift-abi-version", Keys->SwiftABIVersion, 10400116d04dSCyndy Ishida SwiftVersion(0)); 10410116d04dSCyndy Ishida IO.mapOptional("objc-constraint", Keys->ObjCConstraint, 10420116d04dSCyndy Ishida (FileKind == FileType::TBD_V1) 10430116d04dSCyndy Ishida ? ObjCConstraintType::None 10440116d04dSCyndy Ishida : ObjCConstraintType::Retain_Release); 10450116d04dSCyndy Ishida if (FileKind != FileType::TBD_V1) 10460116d04dSCyndy Ishida IO.mapOptional("parent-umbrella", Keys->ParentUmbrella, StringRef()); 10470116d04dSCyndy Ishida IO.mapOptional("exports", Keys->Exports); 10480116d04dSCyndy Ishida if (FileKind != FileType::TBD_V1) 10490116d04dSCyndy Ishida IO.mapOptional("undefineds", Keys->Undefineds); 10500116d04dSCyndy Ishida } 10510116d04dSCyndy Ishida 10520116d04dSCyndy Ishida static void mapKeysToValuesV4(IO &IO, const InterfaceFile *&File) { 10530116d04dSCyndy Ishida MappingNormalization<NormalizedTBD_V4, const InterfaceFile *> Keys(IO, 10540116d04dSCyndy Ishida File); 10550116d04dSCyndy Ishida IO.mapTag("!tapi-tbd", true); 10560116d04dSCyndy Ishida IO.mapRequired("tbd-version", Keys->TBDVersion); 10570116d04dSCyndy Ishida IO.mapRequired("targets", Keys->Targets); 10580116d04dSCyndy Ishida IO.mapOptional("uuids", Keys->UUIDs); 10590116d04dSCyndy Ishida IO.mapOptional("flags", Keys->Flags, TBDFlags::None); 10600116d04dSCyndy Ishida IO.mapRequired("install-name", Keys->InstallName); 10610116d04dSCyndy Ishida IO.mapOptional("current-version", Keys->CurrentVersion, 10620116d04dSCyndy Ishida PackedVersion(1, 0, 0)); 10630116d04dSCyndy Ishida IO.mapOptional("compatibility-version", Keys->CompatibilityVersion, 10640116d04dSCyndy Ishida PackedVersion(1, 0, 0)); 10650116d04dSCyndy Ishida IO.mapOptional("swift-abi-version", Keys->SwiftABIVersion, SwiftVersion(0)); 10660116d04dSCyndy Ishida IO.mapOptional("parent-umbrella", Keys->ParentUmbrellas); 10670116d04dSCyndy Ishida auto OptionKind = MetadataSection::Option::Clients; 10680116d04dSCyndy Ishida IO.mapOptionalWithContext("allowable-clients", Keys->AllowableClients, 10690116d04dSCyndy Ishida OptionKind); 10700116d04dSCyndy Ishida OptionKind = MetadataSection::Option::Libraries; 10710116d04dSCyndy Ishida IO.mapOptionalWithContext("reexported-libraries", Keys->ReexportedLibraries, 10720116d04dSCyndy Ishida OptionKind); 10730116d04dSCyndy Ishida IO.mapOptional("exports", Keys->Exports); 10740116d04dSCyndy Ishida IO.mapOptional("reexports", Keys->Reexports); 10750116d04dSCyndy Ishida IO.mapOptional("undefineds", Keys->Undefineds); 10760116d04dSCyndy Ishida } 10770116d04dSCyndy Ishida }; 10780116d04dSCyndy Ishida 10790116d04dSCyndy Ishida template <> 10800116d04dSCyndy Ishida struct DocumentListTraits<std::vector<const MachO::InterfaceFile *>> { 10810116d04dSCyndy Ishida static size_t size(IO &IO, std::vector<const MachO::InterfaceFile *> &Seq) { 10820116d04dSCyndy Ishida return Seq.size(); 10830116d04dSCyndy Ishida } 10840116d04dSCyndy Ishida static const InterfaceFile *& 10850116d04dSCyndy Ishida element(IO &IO, std::vector<const InterfaceFile *> &Seq, size_t Index) { 10860116d04dSCyndy Ishida if (Index >= Seq.size()) 10870116d04dSCyndy Ishida Seq.resize(Index + 1); 10880116d04dSCyndy Ishida return Seq[Index]; 10890116d04dSCyndy Ishida } 10900116d04dSCyndy Ishida }; 10910116d04dSCyndy Ishida 10920116d04dSCyndy Ishida } // end namespace yaml. 10930116d04dSCyndy Ishida } // namespace llvm 10940116d04dSCyndy Ishida 10950116d04dSCyndy Ishida static void DiagHandler(const SMDiagnostic &Diag, void *Context) { 10960116d04dSCyndy Ishida auto *File = static_cast<TextAPIContext *>(Context); 10970116d04dSCyndy Ishida SmallString<1024> Message; 10980116d04dSCyndy Ishida raw_svector_ostream S(Message); 10990116d04dSCyndy Ishida 11000116d04dSCyndy Ishida SMDiagnostic NewDiag(*Diag.getSourceMgr(), Diag.getLoc(), File->Path, 11010116d04dSCyndy Ishida Diag.getLineNo(), Diag.getColumnNo(), Diag.getKind(), 11020116d04dSCyndy Ishida Diag.getMessage(), Diag.getLineContents(), 11030116d04dSCyndy Ishida Diag.getRanges(), Diag.getFixIts()); 11040116d04dSCyndy Ishida 11050116d04dSCyndy Ishida NewDiag.print(nullptr, S); 11060116d04dSCyndy Ishida File->ErrorMessage = ("malformed file\n" + Message).str(); 11070116d04dSCyndy Ishida } 11080116d04dSCyndy Ishida 11090116d04dSCyndy Ishida Expected<std::unique_ptr<InterfaceFile>> 11100116d04dSCyndy Ishida TextAPIReader::get(MemoryBufferRef InputBuffer) { 11110116d04dSCyndy Ishida TextAPIContext Ctx; 11120116d04dSCyndy Ishida Ctx.Path = std::string(InputBuffer.getBufferIdentifier()); 11130116d04dSCyndy Ishida yaml::Input YAMLIn(InputBuffer.getBuffer(), &Ctx, DiagHandler, &Ctx); 11140116d04dSCyndy Ishida 11150116d04dSCyndy Ishida // Fill vector with interface file objects created by parsing the YAML file. 11160116d04dSCyndy Ishida std::vector<const InterfaceFile *> Files; 11170116d04dSCyndy Ishida YAMLIn >> Files; 11180116d04dSCyndy Ishida 11190116d04dSCyndy Ishida // YAMLIn dynamically allocates for Interface file and in case of error, 11200116d04dSCyndy Ishida // memory leak will occur unless wrapped around unique_ptr 11210116d04dSCyndy Ishida auto File = std::unique_ptr<InterfaceFile>( 11220116d04dSCyndy Ishida const_cast<InterfaceFile *>(Files.front())); 11230116d04dSCyndy Ishida 1124*cfc74024SKazu Hirata for (const InterfaceFile *FI : llvm::drop_begin(Files)) 11250116d04dSCyndy Ishida File->addDocument( 1126*cfc74024SKazu Hirata std::shared_ptr<InterfaceFile>(const_cast<InterfaceFile *>(FI))); 11270116d04dSCyndy Ishida 11280116d04dSCyndy Ishida if (YAMLIn.error()) 11290116d04dSCyndy Ishida return make_error<StringError>(Ctx.ErrorMessage, YAMLIn.error()); 11300116d04dSCyndy Ishida 11310116d04dSCyndy Ishida return std::move(File); 11320116d04dSCyndy Ishida } 11330116d04dSCyndy Ishida 11340116d04dSCyndy Ishida Error TextAPIWriter::writeToStream(raw_ostream &OS, const InterfaceFile &File) { 11350116d04dSCyndy Ishida TextAPIContext Ctx; 11360116d04dSCyndy Ishida Ctx.Path = std::string(File.getPath()); 11370116d04dSCyndy Ishida Ctx.FileKind = File.getFileType(); 11380116d04dSCyndy Ishida llvm::yaml::Output YAMLOut(OS, &Ctx, /*WrapColumn=*/80); 11390116d04dSCyndy Ishida 11400116d04dSCyndy Ishida std::vector<const InterfaceFile *> Files; 11410116d04dSCyndy Ishida Files.emplace_back(&File); 11420116d04dSCyndy Ishida 11430116d04dSCyndy Ishida for (auto Document : File.documents()) 11440116d04dSCyndy Ishida Files.emplace_back(Document.get()); 11450116d04dSCyndy Ishida 11460116d04dSCyndy Ishida // Stream out yaml. 11470116d04dSCyndy Ishida YAMLOut << Files; 11480116d04dSCyndy Ishida 11490116d04dSCyndy Ishida return Error::success(); 11500116d04dSCyndy Ishida } 1151