brintos

brintos / llvm-project-archived public Read only

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