xref: /llvm-project/llvm/lib/TextAPI/InterfaceFile.cpp (revision 03506bc0a99fd53d0f4e3d0bd77eb2f7bad96102)
10116d04dSCyndy Ishida //===- InterfaceFile.cpp --------------------------------------------------===//
20116d04dSCyndy Ishida //
30116d04dSCyndy Ishida // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40116d04dSCyndy Ishida // See https://llvm.org/LICENSE.txt for license information.
50116d04dSCyndy Ishida // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60116d04dSCyndy Ishida //
70116d04dSCyndy Ishida //===----------------------------------------------------------------------===//
80116d04dSCyndy Ishida //
90116d04dSCyndy Ishida // Implements the Interface File.
100116d04dSCyndy Ishida //
110116d04dSCyndy Ishida //===----------------------------------------------------------------------===//
120116d04dSCyndy Ishida 
130116d04dSCyndy Ishida #include "llvm/TextAPI/InterfaceFile.h"
143a080a01SCyndy Ishida #include "llvm/TextAPI/RecordsSlice.h"
1516c1f436SCyndy Ishida #include "llvm/TextAPI/TextAPIError.h"
160116d04dSCyndy Ishida #include <iomanip>
170116d04dSCyndy Ishida #include <sstream>
180116d04dSCyndy Ishida 
190116d04dSCyndy Ishida using namespace llvm;
200116d04dSCyndy Ishida using namespace llvm::MachO;
210116d04dSCyndy Ishida 
220116d04dSCyndy Ishida void InterfaceFileRef::addTarget(const Target &Target) {
230116d04dSCyndy Ishida   addEntry(Targets, Target);
240116d04dSCyndy Ishida }
250116d04dSCyndy Ishida 
260116d04dSCyndy Ishida void InterfaceFile::addAllowableClient(StringRef InstallName,
270116d04dSCyndy Ishida                                        const Target &Target) {
288ca0364dSCyndy Ishida   if (InstallName.empty())
298ca0364dSCyndy Ishida     return;
300116d04dSCyndy Ishida   auto Client = addEntry(AllowableClients, InstallName);
310116d04dSCyndy Ishida   Client->addTarget(Target);
320116d04dSCyndy Ishida }
330116d04dSCyndy Ishida 
340116d04dSCyndy Ishida void InterfaceFile::addReexportedLibrary(StringRef InstallName,
350116d04dSCyndy Ishida                                          const Target &Target) {
368ca0364dSCyndy Ishida   if (InstallName.empty())
378ca0364dSCyndy Ishida     return;
380116d04dSCyndy Ishida   auto Lib = addEntry(ReexportedLibraries, InstallName);
390116d04dSCyndy Ishida   Lib->addTarget(Target);
400116d04dSCyndy Ishida }
410116d04dSCyndy Ishida 
420116d04dSCyndy Ishida void InterfaceFile::addParentUmbrella(const Target &Target_, StringRef Parent) {
438ca0364dSCyndy Ishida   if (Parent.empty())
448ca0364dSCyndy Ishida     return;
450116d04dSCyndy Ishida   auto Iter = lower_bound(ParentUmbrellas, Target_,
460116d04dSCyndy Ishida                           [](const std::pair<Target, std::string> &LHS,
470116d04dSCyndy Ishida                              Target RHS) { return LHS.first < RHS; });
480116d04dSCyndy Ishida 
490116d04dSCyndy Ishida   if ((Iter != ParentUmbrellas.end()) && !(Target_ < Iter->first)) {
500116d04dSCyndy Ishida     Iter->second = std::string(Parent);
510116d04dSCyndy Ishida     return;
520116d04dSCyndy Ishida   }
530116d04dSCyndy Ishida 
540116d04dSCyndy Ishida   ParentUmbrellas.emplace(Iter, Target_, std::string(Parent));
550116d04dSCyndy Ishida }
560116d04dSCyndy Ishida 
57515d3f7dSCyndy Ishida void InterfaceFile::addRPath(StringRef RPath, const Target &InputTarget) {
588ca0364dSCyndy Ishida   if (RPath.empty())
598ca0364dSCyndy Ishida     return;
601a0d6992SCyndy Ishida   using RPathEntryT = const std::pair<Target, std::string>;
611a0d6992SCyndy Ishida   RPathEntryT Entry(InputTarget, RPath);
621a0d6992SCyndy Ishida   auto Iter =
631a0d6992SCyndy Ishida       lower_bound(RPaths, Entry,
641a0d6992SCyndy Ishida                   [](RPathEntryT &LHS, RPathEntryT &RHS) { return LHS < RHS; });
65b70d87bcSCyndy Ishida 
661a0d6992SCyndy Ishida   if ((Iter != RPaths.end()) && (*Iter == Entry))
67b70d87bcSCyndy Ishida     return;
68b70d87bcSCyndy Ishida 
691a0d6992SCyndy Ishida   RPaths.emplace(Iter, Entry);
70b70d87bcSCyndy Ishida }
71b70d87bcSCyndy Ishida 
720116d04dSCyndy Ishida void InterfaceFile::addTarget(const Target &Target) {
730116d04dSCyndy Ishida   addEntry(Targets, Target);
740116d04dSCyndy Ishida }
750116d04dSCyndy Ishida 
760116d04dSCyndy Ishida InterfaceFile::const_filtered_target_range
770116d04dSCyndy Ishida InterfaceFile::targets(ArchitectureSet Archs) const {
780116d04dSCyndy Ishida   std::function<bool(const Target &)> fn = [Archs](const Target &Target_) {
790116d04dSCyndy Ishida     return Archs.has(Target_.Arch);
800116d04dSCyndy Ishida   };
810116d04dSCyndy Ishida   return make_filter_range(Targets, fn);
820116d04dSCyndy Ishida }
830116d04dSCyndy Ishida 
840116d04dSCyndy Ishida void InterfaceFile::addDocument(std::shared_ptr<InterfaceFile> &&Document) {
850116d04dSCyndy Ishida   auto Pos = llvm::lower_bound(Documents, Document,
860116d04dSCyndy Ishida                                [](const std::shared_ptr<InterfaceFile> &LHS,
870116d04dSCyndy Ishida                                   const std::shared_ptr<InterfaceFile> &RHS) {
880116d04dSCyndy Ishida                                  return LHS->InstallName < RHS->InstallName;
890116d04dSCyndy Ishida                                });
901569e0edSCyndy Ishida   assert((Pos == Documents.end() ||
911569e0edSCyndy Ishida           (*Pos)->InstallName != Document->InstallName) &&
921569e0edSCyndy Ishida          "Unexpected duplicate document added");
930116d04dSCyndy Ishida   Document->Parent = this;
940116d04dSCyndy Ishida   Documents.insert(Pos, Document);
950116d04dSCyndy Ishida }
960116d04dSCyndy Ishida 
9716c1f436SCyndy Ishida void InterfaceFile::inlineLibrary(std::shared_ptr<InterfaceFile> Library,
9816c1f436SCyndy Ishida                                   bool Overwrite) {
9916c1f436SCyndy Ishida   auto AddFwk = [&](std::shared_ptr<InterfaceFile> &&Reexport) {
10016c1f436SCyndy Ishida     auto It = lower_bound(
10116c1f436SCyndy Ishida         Documents, Reexport->getInstallName(),
10216c1f436SCyndy Ishida         [](std::shared_ptr<InterfaceFile> &Lhs, const StringRef Rhs) {
10316c1f436SCyndy Ishida           return Lhs->getInstallName() < Rhs;
10416c1f436SCyndy Ishida         });
10516c1f436SCyndy Ishida 
10616c1f436SCyndy Ishida     if (Overwrite && It != Documents.end() &&
10716c1f436SCyndy Ishida         Reexport->getInstallName() == (*It)->getInstallName()) {
10816c1f436SCyndy Ishida       std::replace(Documents.begin(), Documents.end(), *It,
10916c1f436SCyndy Ishida                    std::move(Reexport));
11016c1f436SCyndy Ishida       return;
11116c1f436SCyndy Ishida     }
11216c1f436SCyndy Ishida 
11316c1f436SCyndy Ishida     if ((It != Documents.end()) &&
11416c1f436SCyndy Ishida         !(Reexport->getInstallName() < (*It)->getInstallName()))
11516c1f436SCyndy Ishida       return;
11616c1f436SCyndy Ishida 
11716c1f436SCyndy Ishida     Documents.emplace(It, std::move(Reexport));
11816c1f436SCyndy Ishida   };
11916c1f436SCyndy Ishida   for (auto Doc : Library->documents())
12016c1f436SCyndy Ishida     AddFwk(std::move(Doc));
12116c1f436SCyndy Ishida 
12216c1f436SCyndy Ishida   Library->Documents.clear();
12316c1f436SCyndy Ishida   AddFwk(std::move(Library));
12416c1f436SCyndy Ishida }
12516c1f436SCyndy Ishida 
12616c1f436SCyndy Ishida Expected<std::unique_ptr<InterfaceFile>>
12716c1f436SCyndy Ishida InterfaceFile::merge(const InterfaceFile *O) const {
12816c1f436SCyndy Ishida   // Verify files can be merged.
12916c1f436SCyndy Ishida   if (getInstallName() != O->getInstallName()) {
13016c1f436SCyndy Ishida     return make_error<StringError>("install names do not match",
13116c1f436SCyndy Ishida                                    inconvertibleErrorCode());
13216c1f436SCyndy Ishida   }
13316c1f436SCyndy Ishida 
13416c1f436SCyndy Ishida   if (getCurrentVersion() != O->getCurrentVersion()) {
13516c1f436SCyndy Ishida     return make_error<StringError>("current versions do not match",
13616c1f436SCyndy Ishida                                    inconvertibleErrorCode());
13716c1f436SCyndy Ishida   }
13816c1f436SCyndy Ishida 
13916c1f436SCyndy Ishida   if (getCompatibilityVersion() != O->getCompatibilityVersion()) {
14016c1f436SCyndy Ishida     return make_error<StringError>("compatibility versions do not match",
14116c1f436SCyndy Ishida                                    inconvertibleErrorCode());
14216c1f436SCyndy Ishida   }
14316c1f436SCyndy Ishida 
14416c1f436SCyndy Ishida   if ((getSwiftABIVersion() != 0) && (O->getSwiftABIVersion() != 0) &&
14516c1f436SCyndy Ishida       (getSwiftABIVersion() != O->getSwiftABIVersion())) {
14616c1f436SCyndy Ishida     return make_error<StringError>("swift ABI versions do not match",
14716c1f436SCyndy Ishida                                    inconvertibleErrorCode());
14816c1f436SCyndy Ishida   }
14916c1f436SCyndy Ishida 
15016c1f436SCyndy Ishida   if (isTwoLevelNamespace() != O->isTwoLevelNamespace()) {
15116c1f436SCyndy Ishida     return make_error<StringError>("two level namespace flags do not match",
15216c1f436SCyndy Ishida                                    inconvertibleErrorCode());
15316c1f436SCyndy Ishida   }
15416c1f436SCyndy Ishida 
15516c1f436SCyndy Ishida   if (isApplicationExtensionSafe() != O->isApplicationExtensionSafe()) {
15616c1f436SCyndy Ishida     return make_error<StringError>(
15716c1f436SCyndy Ishida         "application extension safe flags do not match",
15816c1f436SCyndy Ishida         inconvertibleErrorCode());
15916c1f436SCyndy Ishida   }
16016c1f436SCyndy Ishida 
16116c1f436SCyndy Ishida   std::unique_ptr<InterfaceFile> IF(new InterfaceFile());
16216c1f436SCyndy Ishida   IF->setFileType(std::max(getFileType(), O->getFileType()));
16316c1f436SCyndy Ishida   IF->setPath(getPath());
16416c1f436SCyndy Ishida   IF->setInstallName(getInstallName());
16516c1f436SCyndy Ishida   IF->setCurrentVersion(getCurrentVersion());
16616c1f436SCyndy Ishida   IF->setCompatibilityVersion(getCompatibilityVersion());
16716c1f436SCyndy Ishida 
16816c1f436SCyndy Ishida   if (getSwiftABIVersion() == 0)
16916c1f436SCyndy Ishida     IF->setSwiftABIVersion(O->getSwiftABIVersion());
17016c1f436SCyndy Ishida   else
17116c1f436SCyndy Ishida     IF->setSwiftABIVersion(getSwiftABIVersion());
17216c1f436SCyndy Ishida 
17316c1f436SCyndy Ishida   IF->setTwoLevelNamespace(isTwoLevelNamespace());
17416c1f436SCyndy Ishida   IF->setApplicationExtensionSafe(isApplicationExtensionSafe());
175*03506bc0SCyndy Ishida   IF->setOSLibNotForSharedCache(isOSLibNotForSharedCache());
17616c1f436SCyndy Ishida 
17716c1f436SCyndy Ishida   for (const auto &It : umbrellas()) {
17816c1f436SCyndy Ishida     if (!It.second.empty())
17916c1f436SCyndy Ishida       IF->addParentUmbrella(It.first, It.second);
18016c1f436SCyndy Ishida   }
18116c1f436SCyndy Ishida   for (const auto &It : O->umbrellas()) {
18216c1f436SCyndy Ishida     if (!It.second.empty())
18316c1f436SCyndy Ishida       IF->addParentUmbrella(It.first, It.second);
18416c1f436SCyndy Ishida   }
18516c1f436SCyndy Ishida   IF->addTargets(targets());
18616c1f436SCyndy Ishida   IF->addTargets(O->targets());
18716c1f436SCyndy Ishida 
18816c1f436SCyndy Ishida   for (const auto &Lib : allowableClients())
18916c1f436SCyndy Ishida     for (const auto &Target : Lib.targets())
19016c1f436SCyndy Ishida       IF->addAllowableClient(Lib.getInstallName(), Target);
19116c1f436SCyndy Ishida 
19216c1f436SCyndy Ishida   for (const auto &Lib : O->allowableClients())
19316c1f436SCyndy Ishida     for (const auto &Target : Lib.targets())
19416c1f436SCyndy Ishida       IF->addAllowableClient(Lib.getInstallName(), Target);
19516c1f436SCyndy Ishida 
19616c1f436SCyndy Ishida   for (const auto &Lib : reexportedLibraries())
19716c1f436SCyndy Ishida     for (const auto &Target : Lib.targets())
19816c1f436SCyndy Ishida       IF->addReexportedLibrary(Lib.getInstallName(), Target);
19916c1f436SCyndy Ishida 
20016c1f436SCyndy Ishida   for (const auto &Lib : O->reexportedLibraries())
20116c1f436SCyndy Ishida     for (const auto &Target : Lib.targets())
20216c1f436SCyndy Ishida       IF->addReexportedLibrary(Lib.getInstallName(), Target);
20316c1f436SCyndy Ishida 
20416c1f436SCyndy Ishida   for (const auto &[Target, Path] : rpaths())
205515d3f7dSCyndy Ishida     IF->addRPath(Path, Target);
20616c1f436SCyndy Ishida   for (const auto &[Target, Path] : O->rpaths())
207515d3f7dSCyndy Ishida     IF->addRPath(Path, Target);
20816c1f436SCyndy Ishida 
20916c1f436SCyndy Ishida   for (const auto *Sym : symbols()) {
21016c1f436SCyndy Ishida     IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(),
21116c1f436SCyndy Ishida                   Sym->getFlags());
21216c1f436SCyndy Ishida   }
21316c1f436SCyndy Ishida 
21416c1f436SCyndy Ishida   for (const auto *Sym : O->symbols()) {
21516c1f436SCyndy Ishida     IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(),
21616c1f436SCyndy Ishida                   Sym->getFlags());
21716c1f436SCyndy Ishida   }
21816c1f436SCyndy Ishida 
21916c1f436SCyndy Ishida   return std::move(IF);
22016c1f436SCyndy Ishida }
22116c1f436SCyndy Ishida 
22216c1f436SCyndy Ishida Expected<std::unique_ptr<InterfaceFile>>
22316c1f436SCyndy Ishida InterfaceFile::remove(Architecture Arch) const {
22416c1f436SCyndy Ishida   if (getArchitectures() == Arch)
22516c1f436SCyndy Ishida     return make_error<StringError>("cannot remove last architecture slice '" +
22616c1f436SCyndy Ishida                                        getArchitectureName(Arch) + "'",
22716c1f436SCyndy Ishida                                    inconvertibleErrorCode());
22816c1f436SCyndy Ishida 
22916c1f436SCyndy Ishida   if (!getArchitectures().has(Arch)) {
23016c1f436SCyndy Ishida     bool Found = false;
23116c1f436SCyndy Ishida     for (auto &Doc : Documents) {
23216c1f436SCyndy Ishida       if (Doc->getArchitectures().has(Arch)) {
23316c1f436SCyndy Ishida         Found = true;
23416c1f436SCyndy Ishida         break;
23516c1f436SCyndy Ishida       }
23616c1f436SCyndy Ishida     }
23716c1f436SCyndy Ishida 
23816c1f436SCyndy Ishida     if (!Found)
23916c1f436SCyndy Ishida       return make_error<TextAPIError>(TextAPIErrorCode::NoSuchArchitecture);
24016c1f436SCyndy Ishida   }
24116c1f436SCyndy Ishida 
242*03506bc0SCyndy Ishida   // FIXME: Figure out how to keep these attributes in sync when new ones are
243*03506bc0SCyndy Ishida   // added.
24416c1f436SCyndy Ishida   std::unique_ptr<InterfaceFile> IF(new InterfaceFile());
24516c1f436SCyndy Ishida   IF->setFileType(getFileType());
24616c1f436SCyndy Ishida   IF->setPath(getPath());
24716c1f436SCyndy Ishida   IF->addTargets(targets(ArchitectureSet::All().clear(Arch)));
24816c1f436SCyndy Ishida   IF->setInstallName(getInstallName());
24916c1f436SCyndy Ishida   IF->setCurrentVersion(getCurrentVersion());
25016c1f436SCyndy Ishida   IF->setCompatibilityVersion(getCompatibilityVersion());
25116c1f436SCyndy Ishida   IF->setSwiftABIVersion(getSwiftABIVersion());
25216c1f436SCyndy Ishida   IF->setTwoLevelNamespace(isTwoLevelNamespace());
25316c1f436SCyndy Ishida   IF->setApplicationExtensionSafe(isApplicationExtensionSafe());
254*03506bc0SCyndy Ishida   IF->setOSLibNotForSharedCache(isOSLibNotForSharedCache());
25516c1f436SCyndy Ishida   for (const auto &It : umbrellas())
25616c1f436SCyndy Ishida     if (It.first.Arch != Arch)
25716c1f436SCyndy Ishida       IF->addParentUmbrella(It.first, It.second);
25816c1f436SCyndy Ishida 
25916c1f436SCyndy Ishida   for (const auto &Lib : allowableClients()) {
26016c1f436SCyndy Ishida     for (const auto &Target : Lib.targets())
26116c1f436SCyndy Ishida       if (Target.Arch != Arch)
26216c1f436SCyndy Ishida         IF->addAllowableClient(Lib.getInstallName(), Target);
26316c1f436SCyndy Ishida   }
26416c1f436SCyndy Ishida 
26516c1f436SCyndy Ishida   for (const auto &Lib : reexportedLibraries()) {
26616c1f436SCyndy Ishida     for (const auto &Target : Lib.targets())
26716c1f436SCyndy Ishida       if (Target.Arch != Arch)
26816c1f436SCyndy Ishida         IF->addReexportedLibrary(Lib.getInstallName(), Target);
26916c1f436SCyndy Ishida   }
27016c1f436SCyndy Ishida 
27116c1f436SCyndy Ishida   for (const auto *Sym : symbols()) {
27216c1f436SCyndy Ishida     auto Archs = Sym->getArchitectures();
27316c1f436SCyndy Ishida     Archs.clear(Arch);
27416c1f436SCyndy Ishida     if (Archs.empty())
27516c1f436SCyndy Ishida       continue;
27616c1f436SCyndy Ishida 
27716c1f436SCyndy Ishida     IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(Archs),
27816c1f436SCyndy Ishida                   Sym->getFlags());
27916c1f436SCyndy Ishida   }
28016c1f436SCyndy Ishida 
28116c1f436SCyndy Ishida   for (auto &Doc : Documents) {
28216c1f436SCyndy Ishida     // Skip the inlined document if the to be removed architecture is the
28316c1f436SCyndy Ishida     // only one left.
28416c1f436SCyndy Ishida     if (Doc->getArchitectures() == Arch)
28516c1f436SCyndy Ishida       continue;
28616c1f436SCyndy Ishida 
28716c1f436SCyndy Ishida     // If the document doesn't contain the arch, then no work is to be done
28816c1f436SCyndy Ishida     // and it can be copied over.
28916c1f436SCyndy Ishida     if (!Doc->getArchitectures().has(Arch)) {
29016c1f436SCyndy Ishida       auto NewDoc = Doc;
29116c1f436SCyndy Ishida       IF->addDocument(std::move(NewDoc));
29216c1f436SCyndy Ishida       continue;
29316c1f436SCyndy Ishida     }
29416c1f436SCyndy Ishida 
29516c1f436SCyndy Ishida     auto Result = Doc->remove(Arch);
29616c1f436SCyndy Ishida     if (!Result)
29716c1f436SCyndy Ishida       return Result;
29816c1f436SCyndy Ishida 
29916c1f436SCyndy Ishida     IF->addDocument(std::move(Result.get()));
30016c1f436SCyndy Ishida   }
30116c1f436SCyndy Ishida 
30216c1f436SCyndy Ishida   return std::move(IF);
30316c1f436SCyndy Ishida }
30416c1f436SCyndy Ishida 
30516c1f436SCyndy Ishida Expected<std::unique_ptr<InterfaceFile>>
30616c1f436SCyndy Ishida InterfaceFile::extract(Architecture Arch) const {
30716c1f436SCyndy Ishida   if (!getArchitectures().has(Arch)) {
30816c1f436SCyndy Ishida     return make_error<StringError>("file doesn't have architecture '" +
30916c1f436SCyndy Ishida                                        getArchitectureName(Arch) + "'",
31016c1f436SCyndy Ishida                                    inconvertibleErrorCode());
31116c1f436SCyndy Ishida   }
31216c1f436SCyndy Ishida 
31316c1f436SCyndy Ishida   std::unique_ptr<InterfaceFile> IF(new InterfaceFile());
31416c1f436SCyndy Ishida   IF->setFileType(getFileType());
31516c1f436SCyndy Ishida   IF->setPath(getPath());
31616c1f436SCyndy Ishida   IF->addTargets(targets(Arch));
31716c1f436SCyndy Ishida   IF->setInstallName(getInstallName());
31816c1f436SCyndy Ishida   IF->setCurrentVersion(getCurrentVersion());
31916c1f436SCyndy Ishida   IF->setCompatibilityVersion(getCompatibilityVersion());
32016c1f436SCyndy Ishida   IF->setSwiftABIVersion(getSwiftABIVersion());
32116c1f436SCyndy Ishida   IF->setTwoLevelNamespace(isTwoLevelNamespace());
32216c1f436SCyndy Ishida   IF->setApplicationExtensionSafe(isApplicationExtensionSafe());
323*03506bc0SCyndy Ishida   IF->setOSLibNotForSharedCache(isOSLibNotForSharedCache());
32416c1f436SCyndy Ishida   for (const auto &It : umbrellas())
32516c1f436SCyndy Ishida     if (It.first.Arch == Arch)
32616c1f436SCyndy Ishida       IF->addParentUmbrella(It.first, It.second);
32716c1f436SCyndy Ishida 
32816c1f436SCyndy Ishida   for (const auto &It : rpaths())
32916c1f436SCyndy Ishida     if (It.first.Arch == Arch)
330515d3f7dSCyndy Ishida       IF->addRPath(It.second, It.first);
33116c1f436SCyndy Ishida 
33216c1f436SCyndy Ishida   for (const auto &Lib : allowableClients())
33316c1f436SCyndy Ishida     for (const auto &Target : Lib.targets())
33416c1f436SCyndy Ishida       if (Target.Arch == Arch)
33516c1f436SCyndy Ishida         IF->addAllowableClient(Lib.getInstallName(), Target);
33616c1f436SCyndy Ishida 
33716c1f436SCyndy Ishida   for (const auto &Lib : reexportedLibraries())
33816c1f436SCyndy Ishida     for (const auto &Target : Lib.targets())
33916c1f436SCyndy Ishida       if (Target.Arch == Arch)
34016c1f436SCyndy Ishida         IF->addReexportedLibrary(Lib.getInstallName(), Target);
34116c1f436SCyndy Ishida 
34216c1f436SCyndy Ishida   for (const auto *Sym : symbols()) {
34316c1f436SCyndy Ishida     if (Sym->hasArchitecture(Arch))
34416c1f436SCyndy Ishida       IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(Arch),
34516c1f436SCyndy Ishida                     Sym->getFlags());
34616c1f436SCyndy Ishida   }
34716c1f436SCyndy Ishida 
34816c1f436SCyndy Ishida   for (auto &Doc : Documents) {
34916c1f436SCyndy Ishida     // Skip documents that don't have the requested architecture.
35016c1f436SCyndy Ishida     if (!Doc->getArchitectures().has(Arch))
35116c1f436SCyndy Ishida       continue;
35216c1f436SCyndy Ishida 
35316c1f436SCyndy Ishida     auto Result = Doc->extract(Arch);
35416c1f436SCyndy Ishida     if (!Result)
35516c1f436SCyndy Ishida       return Result;
35616c1f436SCyndy Ishida 
35716c1f436SCyndy Ishida     IF->addDocument(std::move(Result.get()));
35816c1f436SCyndy Ishida   }
35916c1f436SCyndy Ishida 
36016c1f436SCyndy Ishida   return std::move(IF);
36116c1f436SCyndy Ishida }
36216c1f436SCyndy Ishida 
3633a080a01SCyndy Ishida void InterfaceFile::setFromBinaryAttrs(const RecordsSlice::BinaryAttrs &BA,
3643a080a01SCyndy Ishida                                        const Target &Targ) {
3653a080a01SCyndy Ishida   if (getFileType() != BA.File)
3663a080a01SCyndy Ishida     setFileType(BA.File);
3673a080a01SCyndy Ishida   if (getInstallName().empty())
3683a080a01SCyndy Ishida     setInstallName(BA.InstallName);
3693a080a01SCyndy Ishida   if (BA.AppExtensionSafe && !isApplicationExtensionSafe())
3703a080a01SCyndy Ishida     setApplicationExtensionSafe();
3713a080a01SCyndy Ishida   if (BA.TwoLevelNamespace && !isTwoLevelNamespace())
3723a080a01SCyndy Ishida     setTwoLevelNamespace();
3733a080a01SCyndy Ishida   if (BA.OSLibNotForSharedCache && !isOSLibNotForSharedCache())
3743a080a01SCyndy Ishida     setOSLibNotForSharedCache();
3753a080a01SCyndy Ishida   if (getCurrentVersion().empty())
3763a080a01SCyndy Ishida     setCurrentVersion(BA.CurrentVersion);
3773a080a01SCyndy Ishida   if (getCompatibilityVersion().empty())
3783a080a01SCyndy Ishida     setCompatibilityVersion(BA.CompatVersion);
3793a080a01SCyndy Ishida   if (getSwiftABIVersion() == 0)
3803a080a01SCyndy Ishida     setSwiftABIVersion(BA.SwiftABI);
3813a080a01SCyndy Ishida   if (getPath().empty())
3823a080a01SCyndy Ishida     setPath(BA.Path);
3833a080a01SCyndy Ishida   if (!BA.ParentUmbrella.empty())
3843a080a01SCyndy Ishida     addParentUmbrella(Targ, BA.ParentUmbrella);
3853a080a01SCyndy Ishida   for (const auto &Client : BA.AllowableClients)
3863a080a01SCyndy Ishida     addAllowableClient(Client, Targ);
3873a080a01SCyndy Ishida   for (const auto &Lib : BA.RexportedLibraries)
3883a080a01SCyndy Ishida     addReexportedLibrary(Lib, Targ);
3893a080a01SCyndy Ishida }
3903a080a01SCyndy Ishida 
391bc85cf16SCyndy Ishida static bool isYAMLTextStub(const FileType &Kind) {
392bc85cf16SCyndy Ishida   return (Kind >= FileType::TBD_V1) && (Kind < FileType::TBD_V5);
393bc85cf16SCyndy Ishida }
394bc85cf16SCyndy Ishida 
3950116d04dSCyndy Ishida bool InterfaceFile::operator==(const InterfaceFile &O) const {
3960116d04dSCyndy Ishida   if (Targets != O.Targets)
3970116d04dSCyndy Ishida     return false;
3980116d04dSCyndy Ishida   if (InstallName != O.InstallName)
3990116d04dSCyndy Ishida     return false;
4000116d04dSCyndy Ishida   if ((CurrentVersion != O.CurrentVersion) ||
4010116d04dSCyndy Ishida       (CompatibilityVersion != O.CompatibilityVersion))
4020116d04dSCyndy Ishida     return false;
4030116d04dSCyndy Ishida   if (SwiftABIVersion != O.SwiftABIVersion)
4040116d04dSCyndy Ishida     return false;
4050116d04dSCyndy Ishida   if (IsTwoLevelNamespace != O.IsTwoLevelNamespace)
4060116d04dSCyndy Ishida     return false;
4070116d04dSCyndy Ishida   if (IsAppExtensionSafe != O.IsAppExtensionSafe)
4080116d04dSCyndy Ishida     return false;
409e17efa60SCyndy Ishida   if (IsOSLibNotForSharedCache != O.IsOSLibNotForSharedCache)
410e17efa60SCyndy Ishida     return false;
411913f21aeSCyndy Ishida   if (HasSimSupport != O.HasSimSupport)
412913f21aeSCyndy Ishida     return false;
4130116d04dSCyndy Ishida   if (ParentUmbrellas != O.ParentUmbrellas)
4140116d04dSCyndy Ishida     return false;
4150116d04dSCyndy Ishida   if (AllowableClients != O.AllowableClients)
4160116d04dSCyndy Ishida     return false;
4170116d04dSCyndy Ishida   if (ReexportedLibraries != O.ReexportedLibraries)
4180116d04dSCyndy Ishida     return false;
4190882c70dSCyndy Ishida   if (*SymbolsSet != *O.SymbolsSet)
4200116d04dSCyndy Ishida     return false;
421bc85cf16SCyndy Ishida   // Don't compare run search paths for older filetypes that cannot express
422bc85cf16SCyndy Ishida   // them.
423bc85cf16SCyndy Ishida   if (!(isYAMLTextStub(FileKind)) && !(isYAMLTextStub(O.FileKind))) {
424bc85cf16SCyndy Ishida     if (RPaths != O.RPaths)
425bc85cf16SCyndy Ishida       return false;
4267de8cd61SCyndy Ishida     if (mapToPlatformVersionSet(Targets) != mapToPlatformVersionSet(O.Targets))
4277de8cd61SCyndy Ishida       return false;
428bc85cf16SCyndy Ishida   }
429bc85cf16SCyndy Ishida 
4300116d04dSCyndy Ishida   if (!std::equal(Documents.begin(), Documents.end(), O.Documents.begin(),
4310116d04dSCyndy Ishida                   O.Documents.end(),
4320116d04dSCyndy Ishida                   [](const std::shared_ptr<InterfaceFile> LHS,
4330116d04dSCyndy Ishida                      const std::shared_ptr<InterfaceFile> RHS) {
4340116d04dSCyndy Ishida                     return *LHS == *RHS;
4350116d04dSCyndy Ishida                   }))
4360116d04dSCyndy Ishida     return false;
4370116d04dSCyndy Ishida   return true;
4380116d04dSCyndy Ishida }
439