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