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