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