Path: blob/main/contrib/llvm-project/llvm/lib/TextAPI/InterfaceFile.cpp
35262 views
//===- InterfaceFile.cpp --------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Implements the Interface File.9//10//===----------------------------------------------------------------------===//1112#include "llvm/TextAPI/InterfaceFile.h"13#include "llvm/TextAPI/RecordsSlice.h"14#include "llvm/TextAPI/TextAPIError.h"15#include <iomanip>16#include <sstream>1718using namespace llvm;19using namespace llvm::MachO;2021void InterfaceFileRef::addTarget(const Target &Target) {22addEntry(Targets, Target);23}2425void InterfaceFile::addAllowableClient(StringRef InstallName,26const Target &Target) {27if (InstallName.empty())28return;29auto Client = addEntry(AllowableClients, InstallName);30Client->addTarget(Target);31}3233void InterfaceFile::addReexportedLibrary(StringRef InstallName,34const Target &Target) {35if (InstallName.empty())36return;37auto Lib = addEntry(ReexportedLibraries, InstallName);38Lib->addTarget(Target);39}4041void InterfaceFile::addParentUmbrella(const Target &Target_, StringRef Parent) {42if (Parent.empty())43return;44auto Iter = lower_bound(ParentUmbrellas, Target_,45[](const std::pair<Target, std::string> &LHS,46Target RHS) { return LHS.first < RHS; });4748if ((Iter != ParentUmbrellas.end()) && !(Target_ < Iter->first)) {49Iter->second = std::string(Parent);50return;51}5253ParentUmbrellas.emplace(Iter, Target_, std::string(Parent));54}5556void InterfaceFile::addRPath(StringRef RPath, const Target &InputTarget) {57if (RPath.empty())58return;59using RPathEntryT = const std::pair<Target, std::string>;60RPathEntryT Entry(InputTarget, RPath);61auto Iter =62lower_bound(RPaths, Entry,63[](RPathEntryT &LHS, RPathEntryT &RHS) { return LHS < RHS; });6465if ((Iter != RPaths.end()) && (*Iter == Entry))66return;6768RPaths.emplace(Iter, Entry);69}7071void InterfaceFile::addTarget(const Target &Target) {72addEntry(Targets, Target);73}7475InterfaceFile::const_filtered_target_range76InterfaceFile::targets(ArchitectureSet Archs) const {77std::function<bool(const Target &)> fn = [Archs](const Target &Target_) {78return Archs.has(Target_.Arch);79};80return make_filter_range(Targets, fn);81}8283void InterfaceFile::addDocument(std::shared_ptr<InterfaceFile> &&Document) {84auto Pos = llvm::lower_bound(Documents, Document,85[](const std::shared_ptr<InterfaceFile> &LHS,86const std::shared_ptr<InterfaceFile> &RHS) {87return LHS->InstallName < RHS->InstallName;88});89Document->Parent = this;90Documents.insert(Pos, Document);91}9293void InterfaceFile::inlineLibrary(std::shared_ptr<InterfaceFile> Library,94bool Overwrite) {95auto AddFwk = [&](std::shared_ptr<InterfaceFile> &&Reexport) {96auto It = lower_bound(97Documents, Reexport->getInstallName(),98[](std::shared_ptr<InterfaceFile> &Lhs, const StringRef Rhs) {99return Lhs->getInstallName() < Rhs;100});101102if (Overwrite && It != Documents.end() &&103Reexport->getInstallName() == (*It)->getInstallName()) {104std::replace(Documents.begin(), Documents.end(), *It,105std::move(Reexport));106return;107}108109if ((It != Documents.end()) &&110!(Reexport->getInstallName() < (*It)->getInstallName()))111return;112113Documents.emplace(It, std::move(Reexport));114};115for (auto Doc : Library->documents())116AddFwk(std::move(Doc));117118Library->Documents.clear();119AddFwk(std::move(Library));120}121122Expected<std::unique_ptr<InterfaceFile>>123InterfaceFile::merge(const InterfaceFile *O) const {124// Verify files can be merged.125if (getInstallName() != O->getInstallName()) {126return make_error<StringError>("install names do not match",127inconvertibleErrorCode());128}129130if (getCurrentVersion() != O->getCurrentVersion()) {131return make_error<StringError>("current versions do not match",132inconvertibleErrorCode());133}134135if (getCompatibilityVersion() != O->getCompatibilityVersion()) {136return make_error<StringError>("compatibility versions do not match",137inconvertibleErrorCode());138}139140if ((getSwiftABIVersion() != 0) && (O->getSwiftABIVersion() != 0) &&141(getSwiftABIVersion() != O->getSwiftABIVersion())) {142return make_error<StringError>("swift ABI versions do not match",143inconvertibleErrorCode());144}145146if (isTwoLevelNamespace() != O->isTwoLevelNamespace()) {147return make_error<StringError>("two level namespace flags do not match",148inconvertibleErrorCode());149}150151if (isApplicationExtensionSafe() != O->isApplicationExtensionSafe()) {152return make_error<StringError>(153"application extension safe flags do not match",154inconvertibleErrorCode());155}156157std::unique_ptr<InterfaceFile> IF(new InterfaceFile());158IF->setFileType(std::max(getFileType(), O->getFileType()));159IF->setPath(getPath());160IF->setInstallName(getInstallName());161IF->setCurrentVersion(getCurrentVersion());162IF->setCompatibilityVersion(getCompatibilityVersion());163164if (getSwiftABIVersion() == 0)165IF->setSwiftABIVersion(O->getSwiftABIVersion());166else167IF->setSwiftABIVersion(getSwiftABIVersion());168169IF->setTwoLevelNamespace(isTwoLevelNamespace());170IF->setApplicationExtensionSafe(isApplicationExtensionSafe());171172for (const auto &It : umbrellas()) {173if (!It.second.empty())174IF->addParentUmbrella(It.first, It.second);175}176for (const auto &It : O->umbrellas()) {177if (!It.second.empty())178IF->addParentUmbrella(It.first, It.second);179}180IF->addTargets(targets());181IF->addTargets(O->targets());182183for (const auto &Lib : allowableClients())184for (const auto &Target : Lib.targets())185IF->addAllowableClient(Lib.getInstallName(), Target);186187for (const auto &Lib : O->allowableClients())188for (const auto &Target : Lib.targets())189IF->addAllowableClient(Lib.getInstallName(), Target);190191for (const auto &Lib : reexportedLibraries())192for (const auto &Target : Lib.targets())193IF->addReexportedLibrary(Lib.getInstallName(), Target);194195for (const auto &Lib : O->reexportedLibraries())196for (const auto &Target : Lib.targets())197IF->addReexportedLibrary(Lib.getInstallName(), Target);198199for (const auto &[Target, Path] : rpaths())200IF->addRPath(Path, Target);201for (const auto &[Target, Path] : O->rpaths())202IF->addRPath(Path, Target);203204for (const auto *Sym : symbols()) {205IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(),206Sym->getFlags());207}208209for (const auto *Sym : O->symbols()) {210IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(),211Sym->getFlags());212}213214return std::move(IF);215}216217Expected<std::unique_ptr<InterfaceFile>>218InterfaceFile::remove(Architecture Arch) const {219if (getArchitectures() == Arch)220return make_error<StringError>("cannot remove last architecture slice '" +221getArchitectureName(Arch) + "'",222inconvertibleErrorCode());223224if (!getArchitectures().has(Arch)) {225bool Found = false;226for (auto &Doc : Documents) {227if (Doc->getArchitectures().has(Arch)) {228Found = true;229break;230}231}232233if (!Found)234return make_error<TextAPIError>(TextAPIErrorCode::NoSuchArchitecture);235}236237std::unique_ptr<InterfaceFile> IF(new InterfaceFile());238IF->setFileType(getFileType());239IF->setPath(getPath());240IF->addTargets(targets(ArchitectureSet::All().clear(Arch)));241IF->setInstallName(getInstallName());242IF->setCurrentVersion(getCurrentVersion());243IF->setCompatibilityVersion(getCompatibilityVersion());244IF->setSwiftABIVersion(getSwiftABIVersion());245IF->setTwoLevelNamespace(isTwoLevelNamespace());246IF->setApplicationExtensionSafe(isApplicationExtensionSafe());247for (const auto &It : umbrellas())248if (It.first.Arch != Arch)249IF->addParentUmbrella(It.first, It.second);250251for (const auto &Lib : allowableClients()) {252for (const auto &Target : Lib.targets())253if (Target.Arch != Arch)254IF->addAllowableClient(Lib.getInstallName(), Target);255}256257for (const auto &Lib : reexportedLibraries()) {258for (const auto &Target : Lib.targets())259if (Target.Arch != Arch)260IF->addReexportedLibrary(Lib.getInstallName(), Target);261}262263for (const auto *Sym : symbols()) {264auto Archs = Sym->getArchitectures();265Archs.clear(Arch);266if (Archs.empty())267continue;268269IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(Archs),270Sym->getFlags());271}272273for (auto &Doc : Documents) {274// Skip the inlined document if the to be removed architecture is the275// only one left.276if (Doc->getArchitectures() == Arch)277continue;278279// If the document doesn't contain the arch, then no work is to be done280// and it can be copied over.281if (!Doc->getArchitectures().has(Arch)) {282auto NewDoc = Doc;283IF->addDocument(std::move(NewDoc));284continue;285}286287auto Result = Doc->remove(Arch);288if (!Result)289return Result;290291IF->addDocument(std::move(Result.get()));292}293294return std::move(IF);295}296297Expected<std::unique_ptr<InterfaceFile>>298InterfaceFile::extract(Architecture Arch) const {299if (!getArchitectures().has(Arch)) {300return make_error<StringError>("file doesn't have architecture '" +301getArchitectureName(Arch) + "'",302inconvertibleErrorCode());303}304305std::unique_ptr<InterfaceFile> IF(new InterfaceFile());306IF->setFileType(getFileType());307IF->setPath(getPath());308IF->addTargets(targets(Arch));309IF->setInstallName(getInstallName());310IF->setCurrentVersion(getCurrentVersion());311IF->setCompatibilityVersion(getCompatibilityVersion());312IF->setSwiftABIVersion(getSwiftABIVersion());313IF->setTwoLevelNamespace(isTwoLevelNamespace());314IF->setApplicationExtensionSafe(isApplicationExtensionSafe());315for (const auto &It : umbrellas())316if (It.first.Arch == Arch)317IF->addParentUmbrella(It.first, It.second);318319for (const auto &It : rpaths())320if (It.first.Arch == Arch)321IF->addRPath(It.second, It.first);322323for (const auto &Lib : allowableClients())324for (const auto &Target : Lib.targets())325if (Target.Arch == Arch)326IF->addAllowableClient(Lib.getInstallName(), Target);327328for (const auto &Lib : reexportedLibraries())329for (const auto &Target : Lib.targets())330if (Target.Arch == Arch)331IF->addReexportedLibrary(Lib.getInstallName(), Target);332333for (const auto *Sym : symbols()) {334if (Sym->hasArchitecture(Arch))335IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(Arch),336Sym->getFlags());337}338339for (auto &Doc : Documents) {340// Skip documents that don't have the requested architecture.341if (!Doc->getArchitectures().has(Arch))342continue;343344auto Result = Doc->extract(Arch);345if (!Result)346return Result;347348IF->addDocument(std::move(Result.get()));349}350351return std::move(IF);352}353354void InterfaceFile::setFromBinaryAttrs(const RecordsSlice::BinaryAttrs &BA,355const Target &Targ) {356if (getFileType() != BA.File)357setFileType(BA.File);358if (getInstallName().empty())359setInstallName(BA.InstallName);360if (BA.AppExtensionSafe && !isApplicationExtensionSafe())361setApplicationExtensionSafe();362if (BA.TwoLevelNamespace && !isTwoLevelNamespace())363setTwoLevelNamespace();364if (BA.OSLibNotForSharedCache && !isOSLibNotForSharedCache())365setOSLibNotForSharedCache();366if (getCurrentVersion().empty())367setCurrentVersion(BA.CurrentVersion);368if (getCompatibilityVersion().empty())369setCompatibilityVersion(BA.CompatVersion);370if (getSwiftABIVersion() == 0)371setSwiftABIVersion(BA.SwiftABI);372if (getPath().empty())373setPath(BA.Path);374if (!BA.ParentUmbrella.empty())375addParentUmbrella(Targ, BA.ParentUmbrella);376for (const auto &Client : BA.AllowableClients)377addAllowableClient(Client, Targ);378for (const auto &Lib : BA.RexportedLibraries)379addReexportedLibrary(Lib, Targ);380}381382static bool isYAMLTextStub(const FileType &Kind) {383return (Kind >= FileType::TBD_V1) && (Kind < FileType::TBD_V5);384}385386bool InterfaceFile::operator==(const InterfaceFile &O) const {387if (Targets != O.Targets)388return false;389if (InstallName != O.InstallName)390return false;391if ((CurrentVersion != O.CurrentVersion) ||392(CompatibilityVersion != O.CompatibilityVersion))393return false;394if (SwiftABIVersion != O.SwiftABIVersion)395return false;396if (IsTwoLevelNamespace != O.IsTwoLevelNamespace)397return false;398if (IsAppExtensionSafe != O.IsAppExtensionSafe)399return false;400if (IsOSLibNotForSharedCache != O.IsOSLibNotForSharedCache)401return false;402if (HasSimSupport != O.HasSimSupport)403return false;404if (ParentUmbrellas != O.ParentUmbrellas)405return false;406if (AllowableClients != O.AllowableClients)407return false;408if (ReexportedLibraries != O.ReexportedLibraries)409return false;410if (*SymbolsSet != *O.SymbolsSet)411return false;412// Don't compare run search paths for older filetypes that cannot express413// them.414if (!(isYAMLTextStub(FileKind)) && !(isYAMLTextStub(O.FileKind))) {415if (RPaths != O.RPaths)416return false;417if (mapToPlatformVersionSet(Targets) != mapToPlatformVersionSet(O.Targets))418return false;419}420421if (!std::equal(Documents.begin(), Documents.end(), O.Documents.begin(),422O.Documents.end(),423[](const std::shared_ptr<InterfaceFile> LHS,424const std::shared_ptr<InterfaceFile> RHS) {425return *LHS == *RHS;426}))427return false;428return true;429}430431432