diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-12-18 20:30:12 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2024-04-06 20:11:55 +0000 |
commit | 5f757f3ff9144b609b3c433dfd370cc6bdc191ad (patch) | |
tree | 1b4e980b866cd26a00af34c0a653eb640bd09caf /contrib/llvm-project/llvm/lib/TextAPI/InterfaceFile.cpp | |
parent | 3e1c8a35f741a5d114d0ba670b15191355711fe9 (diff) | |
parent | 312c0ed19cc5276a17bacf2120097bec4515b0f1 (diff) |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/TextAPI/InterfaceFile.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/TextAPI/InterfaceFile.cpp | 280 |
1 files changed, 273 insertions, 7 deletions
diff --git a/contrib/llvm-project/llvm/lib/TextAPI/InterfaceFile.cpp b/contrib/llvm-project/llvm/lib/TextAPI/InterfaceFile.cpp index b7f967aa754e..3689ab919191 100644 --- a/contrib/llvm-project/llvm/lib/TextAPI/InterfaceFile.cpp +++ b/contrib/llvm-project/llvm/lib/TextAPI/InterfaceFile.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "llvm/TextAPI/InterfaceFile.h" +#include "llvm/TextAPI/TextAPIError.h" #include <iomanip> #include <sstream> @@ -47,16 +48,16 @@ void InterfaceFile::addParentUmbrella(const Target &Target_, StringRef Parent) { } void InterfaceFile::addRPath(const Target &InputTarget, StringRef RPath) { - auto Iter = lower_bound(RPaths, InputTarget, - [](const std::pair<Target, std::string> &LHS, - Target RHS) { return LHS.first < RHS; }); + using RPathEntryT = const std::pair<Target, std::string>; + RPathEntryT Entry(InputTarget, RPath); + auto Iter = + lower_bound(RPaths, Entry, + [](RPathEntryT &LHS, RPathEntryT &RHS) { return LHS < RHS; }); - if ((Iter != RPaths.end()) && !(InputTarget < Iter->first)) { - Iter->second = std::string(RPath); + if ((Iter != RPaths.end()) && (*Iter == Entry)) return; - } - RPaths.emplace(Iter, InputTarget, std::string(RPath)); + RPaths.emplace(Iter, Entry); } void InterfaceFile::addTarget(const Target &Target) { @@ -81,6 +82,267 @@ void InterfaceFile::addDocument(std::shared_ptr<InterfaceFile> &&Document) { Documents.insert(Pos, Document); } +void InterfaceFile::inlineLibrary(std::shared_ptr<InterfaceFile> Library, + bool Overwrite) { + auto AddFwk = [&](std::shared_ptr<InterfaceFile> &&Reexport) { + auto It = lower_bound( + Documents, Reexport->getInstallName(), + [](std::shared_ptr<InterfaceFile> &Lhs, const StringRef Rhs) { + return Lhs->getInstallName() < Rhs; + }); + + if (Overwrite && It != Documents.end() && + Reexport->getInstallName() == (*It)->getInstallName()) { + std::replace(Documents.begin(), Documents.end(), *It, + std::move(Reexport)); + return; + } + + if ((It != Documents.end()) && + !(Reexport->getInstallName() < (*It)->getInstallName())) + return; + + Documents.emplace(It, std::move(Reexport)); + }; + for (auto Doc : Library->documents()) + AddFwk(std::move(Doc)); + + Library->Documents.clear(); + AddFwk(std::move(Library)); +} + +Expected<std::unique_ptr<InterfaceFile>> +InterfaceFile::merge(const InterfaceFile *O) const { + // Verify files can be merged. + if (getInstallName() != O->getInstallName()) { + return make_error<StringError>("install names do not match", + inconvertibleErrorCode()); + } + + if (getCurrentVersion() != O->getCurrentVersion()) { + return make_error<StringError>("current versions do not match", + inconvertibleErrorCode()); + } + + if (getCompatibilityVersion() != O->getCompatibilityVersion()) { + return make_error<StringError>("compatibility versions do not match", + inconvertibleErrorCode()); + } + + if ((getSwiftABIVersion() != 0) && (O->getSwiftABIVersion() != 0) && + (getSwiftABIVersion() != O->getSwiftABIVersion())) { + return make_error<StringError>("swift ABI versions do not match", + inconvertibleErrorCode()); + } + + if (isTwoLevelNamespace() != O->isTwoLevelNamespace()) { + return make_error<StringError>("two level namespace flags do not match", + inconvertibleErrorCode()); + } + + if (isApplicationExtensionSafe() != O->isApplicationExtensionSafe()) { + return make_error<StringError>( + "application extension safe flags do not match", + inconvertibleErrorCode()); + } + + std::unique_ptr<InterfaceFile> IF(new InterfaceFile()); + IF->setFileType(std::max(getFileType(), O->getFileType())); + IF->setPath(getPath()); + IF->setInstallName(getInstallName()); + IF->setCurrentVersion(getCurrentVersion()); + IF->setCompatibilityVersion(getCompatibilityVersion()); + + if (getSwiftABIVersion() == 0) + IF->setSwiftABIVersion(O->getSwiftABIVersion()); + else + IF->setSwiftABIVersion(getSwiftABIVersion()); + + IF->setTwoLevelNamespace(isTwoLevelNamespace()); + IF->setApplicationExtensionSafe(isApplicationExtensionSafe()); + + for (const auto &It : umbrellas()) { + if (!It.second.empty()) + IF->addParentUmbrella(It.first, It.second); + } + for (const auto &It : O->umbrellas()) { + if (!It.second.empty()) + IF->addParentUmbrella(It.first, It.second); + } + IF->addTargets(targets()); + IF->addTargets(O->targets()); + + for (const auto &Lib : allowableClients()) + for (const auto &Target : Lib.targets()) + IF->addAllowableClient(Lib.getInstallName(), Target); + + for (const auto &Lib : O->allowableClients()) + for (const auto &Target : Lib.targets()) + IF->addAllowableClient(Lib.getInstallName(), Target); + + for (const auto &Lib : reexportedLibraries()) + for (const auto &Target : Lib.targets()) + IF->addReexportedLibrary(Lib.getInstallName(), Target); + + for (const auto &Lib : O->reexportedLibraries()) + for (const auto &Target : Lib.targets()) + IF->addReexportedLibrary(Lib.getInstallName(), Target); + + for (const auto &[Target, Path] : rpaths()) + IF->addRPath(Target, Path); + for (const auto &[Target, Path] : O->rpaths()) + IF->addRPath(Target, Path); + + for (const auto *Sym : symbols()) { + IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(), + Sym->getFlags()); + } + + for (const auto *Sym : O->symbols()) { + IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(), + Sym->getFlags()); + } + + return std::move(IF); +} + +Expected<std::unique_ptr<InterfaceFile>> +InterfaceFile::remove(Architecture Arch) const { + if (getArchitectures() == Arch) + return make_error<StringError>("cannot remove last architecture slice '" + + getArchitectureName(Arch) + "'", + inconvertibleErrorCode()); + + if (!getArchitectures().has(Arch)) { + bool Found = false; + for (auto &Doc : Documents) { + if (Doc->getArchitectures().has(Arch)) { + Found = true; + break; + } + } + + if (!Found) + return make_error<TextAPIError>(TextAPIErrorCode::NoSuchArchitecture); + } + + std::unique_ptr<InterfaceFile> IF(new InterfaceFile()); + IF->setFileType(getFileType()); + IF->setPath(getPath()); + IF->addTargets(targets(ArchitectureSet::All().clear(Arch))); + IF->setInstallName(getInstallName()); + IF->setCurrentVersion(getCurrentVersion()); + IF->setCompatibilityVersion(getCompatibilityVersion()); + IF->setSwiftABIVersion(getSwiftABIVersion()); + IF->setTwoLevelNamespace(isTwoLevelNamespace()); + IF->setApplicationExtensionSafe(isApplicationExtensionSafe()); + for (const auto &It : umbrellas()) + if (It.first.Arch != Arch) + IF->addParentUmbrella(It.first, It.second); + + for (const auto &Lib : allowableClients()) { + for (const auto &Target : Lib.targets()) + if (Target.Arch != Arch) + IF->addAllowableClient(Lib.getInstallName(), Target); + } + + for (const auto &Lib : reexportedLibraries()) { + for (const auto &Target : Lib.targets()) + if (Target.Arch != Arch) + IF->addReexportedLibrary(Lib.getInstallName(), Target); + } + + for (const auto *Sym : symbols()) { + auto Archs = Sym->getArchitectures(); + Archs.clear(Arch); + if (Archs.empty()) + continue; + + IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(Archs), + Sym->getFlags()); + } + + for (auto &Doc : Documents) { + // Skip the inlined document if the to be removed architecture is the + // only one left. + if (Doc->getArchitectures() == Arch) + continue; + + // If the document doesn't contain the arch, then no work is to be done + // and it can be copied over. + if (!Doc->getArchitectures().has(Arch)) { + auto NewDoc = Doc; + IF->addDocument(std::move(NewDoc)); + continue; + } + + auto Result = Doc->remove(Arch); + if (!Result) + return Result; + + IF->addDocument(std::move(Result.get())); + } + + return std::move(IF); +} + +Expected<std::unique_ptr<InterfaceFile>> +InterfaceFile::extract(Architecture Arch) const { + if (!getArchitectures().has(Arch)) { + return make_error<StringError>("file doesn't have architecture '" + + getArchitectureName(Arch) + "'", + inconvertibleErrorCode()); + } + + std::unique_ptr<InterfaceFile> IF(new InterfaceFile()); + IF->setFileType(getFileType()); + IF->setPath(getPath()); + IF->addTargets(targets(Arch)); + IF->setInstallName(getInstallName()); + IF->setCurrentVersion(getCurrentVersion()); + IF->setCompatibilityVersion(getCompatibilityVersion()); + IF->setSwiftABIVersion(getSwiftABIVersion()); + IF->setTwoLevelNamespace(isTwoLevelNamespace()); + IF->setApplicationExtensionSafe(isApplicationExtensionSafe()); + for (const auto &It : umbrellas()) + if (It.first.Arch == Arch) + IF->addParentUmbrella(It.first, It.second); + + for (const auto &It : rpaths()) + if (It.first.Arch == Arch) + IF->addRPath(It.first, It.second); + + for (const auto &Lib : allowableClients()) + for (const auto &Target : Lib.targets()) + if (Target.Arch == Arch) + IF->addAllowableClient(Lib.getInstallName(), Target); + + for (const auto &Lib : reexportedLibraries()) + for (const auto &Target : Lib.targets()) + if (Target.Arch == Arch) + IF->addReexportedLibrary(Lib.getInstallName(), Target); + + for (const auto *Sym : symbols()) { + if (Sym->hasArchitecture(Arch)) + IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(Arch), + Sym->getFlags()); + } + + for (auto &Doc : Documents) { + // Skip documents that don't have the requested architecture. + if (!Doc->getArchitectures().has(Arch)) + continue; + + auto Result = Doc->extract(Arch); + if (!Result) + return Result; + + IF->addDocument(std::move(Result.get())); + } + + return std::move(IF); +} + static bool isYAMLTextStub(const FileType &Kind) { return (Kind >= FileType::TBD_V1) && (Kind < FileType::TBD_V5); } @@ -99,6 +361,10 @@ bool InterfaceFile::operator==(const InterfaceFile &O) const { return false; if (IsAppExtensionSafe != O.IsAppExtensionSafe) return false; + if (IsOSLibNotForSharedCache != O.IsOSLibNotForSharedCache) + return false; + if (HasSimSupport != O.HasSimSupport) + return false; if (ParentUmbrellas != O.ParentUmbrellas) return false; if (AllowableClients != O.AllowableClients) |