xref: /freebsd-src/contrib/llvm-project/llvm/lib/TextAPI/InterfaceFile.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1fe6060f1SDimitry Andric //===- InterfaceFile.cpp --------------------------------------------------===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric //
9fe6060f1SDimitry Andric // Implements the Interface File.
10fe6060f1SDimitry Andric //
11fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
12fe6060f1SDimitry Andric 
13fe6060f1SDimitry Andric #include "llvm/TextAPI/InterfaceFile.h"
14*5f757f3fSDimitry Andric #include "llvm/TextAPI/TextAPIError.h"
15fe6060f1SDimitry Andric #include <iomanip>
16fe6060f1SDimitry Andric #include <sstream>
17fe6060f1SDimitry Andric 
18fe6060f1SDimitry Andric using namespace llvm;
19fe6060f1SDimitry Andric using namespace llvm::MachO;
20fe6060f1SDimitry Andric 
21fe6060f1SDimitry Andric void InterfaceFileRef::addTarget(const Target &Target) {
22fe6060f1SDimitry Andric   addEntry(Targets, Target);
23fe6060f1SDimitry Andric }
24fe6060f1SDimitry Andric 
25fe6060f1SDimitry Andric void InterfaceFile::addAllowableClient(StringRef InstallName,
26fe6060f1SDimitry Andric                                        const Target &Target) {
27fe6060f1SDimitry Andric   auto Client = addEntry(AllowableClients, InstallName);
28fe6060f1SDimitry Andric   Client->addTarget(Target);
29fe6060f1SDimitry Andric }
30fe6060f1SDimitry Andric 
31fe6060f1SDimitry Andric void InterfaceFile::addReexportedLibrary(StringRef InstallName,
32fe6060f1SDimitry Andric                                          const Target &Target) {
33fe6060f1SDimitry Andric   auto Lib = addEntry(ReexportedLibraries, InstallName);
34fe6060f1SDimitry Andric   Lib->addTarget(Target);
35fe6060f1SDimitry Andric }
36fe6060f1SDimitry Andric 
37fe6060f1SDimitry Andric void InterfaceFile::addParentUmbrella(const Target &Target_, StringRef Parent) {
38fe6060f1SDimitry Andric   auto Iter = lower_bound(ParentUmbrellas, Target_,
39fe6060f1SDimitry Andric                           [](const std::pair<Target, std::string> &LHS,
40fe6060f1SDimitry Andric                              Target RHS) { return LHS.first < RHS; });
41fe6060f1SDimitry Andric 
42fe6060f1SDimitry Andric   if ((Iter != ParentUmbrellas.end()) && !(Target_ < Iter->first)) {
43fe6060f1SDimitry Andric     Iter->second = std::string(Parent);
44fe6060f1SDimitry Andric     return;
45fe6060f1SDimitry Andric   }
46fe6060f1SDimitry Andric 
47fe6060f1SDimitry Andric   ParentUmbrellas.emplace(Iter, Target_, std::string(Parent));
48fe6060f1SDimitry Andric }
49fe6060f1SDimitry Andric 
5006c3fb27SDimitry Andric void InterfaceFile::addRPath(const Target &InputTarget, StringRef RPath) {
51*5f757f3fSDimitry Andric   using RPathEntryT = const std::pair<Target, std::string>;
52*5f757f3fSDimitry Andric   RPathEntryT Entry(InputTarget, RPath);
53*5f757f3fSDimitry Andric   auto Iter =
54*5f757f3fSDimitry Andric       lower_bound(RPaths, Entry,
55*5f757f3fSDimitry Andric                   [](RPathEntryT &LHS, RPathEntryT &RHS) { return LHS < RHS; });
56fe6060f1SDimitry Andric 
57*5f757f3fSDimitry Andric   if ((Iter != RPaths.end()) && (*Iter == Entry))
58fe6060f1SDimitry Andric     return;
59fe6060f1SDimitry Andric 
60*5f757f3fSDimitry Andric   RPaths.emplace(Iter, Entry);
61fe6060f1SDimitry Andric }
62fe6060f1SDimitry Andric 
63fe6060f1SDimitry Andric void InterfaceFile::addTarget(const Target &Target) {
64fe6060f1SDimitry Andric   addEntry(Targets, Target);
65fe6060f1SDimitry Andric }
66fe6060f1SDimitry Andric 
67fe6060f1SDimitry Andric InterfaceFile::const_filtered_target_range
68fe6060f1SDimitry Andric InterfaceFile::targets(ArchitectureSet Archs) const {
69fe6060f1SDimitry Andric   std::function<bool(const Target &)> fn = [Archs](const Target &Target_) {
70fe6060f1SDimitry Andric     return Archs.has(Target_.Arch);
71fe6060f1SDimitry Andric   };
72fe6060f1SDimitry Andric   return make_filter_range(Targets, fn);
73fe6060f1SDimitry Andric }
74fe6060f1SDimitry Andric 
75fe6060f1SDimitry Andric void InterfaceFile::addDocument(std::shared_ptr<InterfaceFile> &&Document) {
76fe6060f1SDimitry Andric   auto Pos = llvm::lower_bound(Documents, Document,
77fe6060f1SDimitry Andric                                [](const std::shared_ptr<InterfaceFile> &LHS,
78fe6060f1SDimitry Andric                                   const std::shared_ptr<InterfaceFile> &RHS) {
79fe6060f1SDimitry Andric                                  return LHS->InstallName < RHS->InstallName;
80fe6060f1SDimitry Andric                                });
81fe6060f1SDimitry Andric   Document->Parent = this;
82fe6060f1SDimitry Andric   Documents.insert(Pos, Document);
83fe6060f1SDimitry Andric }
84fe6060f1SDimitry Andric 
85*5f757f3fSDimitry Andric void InterfaceFile::inlineLibrary(std::shared_ptr<InterfaceFile> Library,
86*5f757f3fSDimitry Andric                                   bool Overwrite) {
87*5f757f3fSDimitry Andric   auto AddFwk = [&](std::shared_ptr<InterfaceFile> &&Reexport) {
88*5f757f3fSDimitry Andric     auto It = lower_bound(
89*5f757f3fSDimitry Andric         Documents, Reexport->getInstallName(),
90*5f757f3fSDimitry Andric         [](std::shared_ptr<InterfaceFile> &Lhs, const StringRef Rhs) {
91*5f757f3fSDimitry Andric           return Lhs->getInstallName() < Rhs;
92*5f757f3fSDimitry Andric         });
93*5f757f3fSDimitry Andric 
94*5f757f3fSDimitry Andric     if (Overwrite && It != Documents.end() &&
95*5f757f3fSDimitry Andric         Reexport->getInstallName() == (*It)->getInstallName()) {
96*5f757f3fSDimitry Andric       std::replace(Documents.begin(), Documents.end(), *It,
97*5f757f3fSDimitry Andric                    std::move(Reexport));
98*5f757f3fSDimitry Andric       return;
99*5f757f3fSDimitry Andric     }
100*5f757f3fSDimitry Andric 
101*5f757f3fSDimitry Andric     if ((It != Documents.end()) &&
102*5f757f3fSDimitry Andric         !(Reexport->getInstallName() < (*It)->getInstallName()))
103*5f757f3fSDimitry Andric       return;
104*5f757f3fSDimitry Andric 
105*5f757f3fSDimitry Andric     Documents.emplace(It, std::move(Reexport));
106*5f757f3fSDimitry Andric   };
107*5f757f3fSDimitry Andric   for (auto Doc : Library->documents())
108*5f757f3fSDimitry Andric     AddFwk(std::move(Doc));
109*5f757f3fSDimitry Andric 
110*5f757f3fSDimitry Andric   Library->Documents.clear();
111*5f757f3fSDimitry Andric   AddFwk(std::move(Library));
112*5f757f3fSDimitry Andric }
113*5f757f3fSDimitry Andric 
114*5f757f3fSDimitry Andric Expected<std::unique_ptr<InterfaceFile>>
115*5f757f3fSDimitry Andric InterfaceFile::merge(const InterfaceFile *O) const {
116*5f757f3fSDimitry Andric   // Verify files can be merged.
117*5f757f3fSDimitry Andric   if (getInstallName() != O->getInstallName()) {
118*5f757f3fSDimitry Andric     return make_error<StringError>("install names do not match",
119*5f757f3fSDimitry Andric                                    inconvertibleErrorCode());
120*5f757f3fSDimitry Andric   }
121*5f757f3fSDimitry Andric 
122*5f757f3fSDimitry Andric   if (getCurrentVersion() != O->getCurrentVersion()) {
123*5f757f3fSDimitry Andric     return make_error<StringError>("current versions do not match",
124*5f757f3fSDimitry Andric                                    inconvertibleErrorCode());
125*5f757f3fSDimitry Andric   }
126*5f757f3fSDimitry Andric 
127*5f757f3fSDimitry Andric   if (getCompatibilityVersion() != O->getCompatibilityVersion()) {
128*5f757f3fSDimitry Andric     return make_error<StringError>("compatibility versions do not match",
129*5f757f3fSDimitry Andric                                    inconvertibleErrorCode());
130*5f757f3fSDimitry Andric   }
131*5f757f3fSDimitry Andric 
132*5f757f3fSDimitry Andric   if ((getSwiftABIVersion() != 0) && (O->getSwiftABIVersion() != 0) &&
133*5f757f3fSDimitry Andric       (getSwiftABIVersion() != O->getSwiftABIVersion())) {
134*5f757f3fSDimitry Andric     return make_error<StringError>("swift ABI versions do not match",
135*5f757f3fSDimitry Andric                                    inconvertibleErrorCode());
136*5f757f3fSDimitry Andric   }
137*5f757f3fSDimitry Andric 
138*5f757f3fSDimitry Andric   if (isTwoLevelNamespace() != O->isTwoLevelNamespace()) {
139*5f757f3fSDimitry Andric     return make_error<StringError>("two level namespace flags do not match",
140*5f757f3fSDimitry Andric                                    inconvertibleErrorCode());
141*5f757f3fSDimitry Andric   }
142*5f757f3fSDimitry Andric 
143*5f757f3fSDimitry Andric   if (isApplicationExtensionSafe() != O->isApplicationExtensionSafe()) {
144*5f757f3fSDimitry Andric     return make_error<StringError>(
145*5f757f3fSDimitry Andric         "application extension safe flags do not match",
146*5f757f3fSDimitry Andric         inconvertibleErrorCode());
147*5f757f3fSDimitry Andric   }
148*5f757f3fSDimitry Andric 
149*5f757f3fSDimitry Andric   std::unique_ptr<InterfaceFile> IF(new InterfaceFile());
150*5f757f3fSDimitry Andric   IF->setFileType(std::max(getFileType(), O->getFileType()));
151*5f757f3fSDimitry Andric   IF->setPath(getPath());
152*5f757f3fSDimitry Andric   IF->setInstallName(getInstallName());
153*5f757f3fSDimitry Andric   IF->setCurrentVersion(getCurrentVersion());
154*5f757f3fSDimitry Andric   IF->setCompatibilityVersion(getCompatibilityVersion());
155*5f757f3fSDimitry Andric 
156*5f757f3fSDimitry Andric   if (getSwiftABIVersion() == 0)
157*5f757f3fSDimitry Andric     IF->setSwiftABIVersion(O->getSwiftABIVersion());
158*5f757f3fSDimitry Andric   else
159*5f757f3fSDimitry Andric     IF->setSwiftABIVersion(getSwiftABIVersion());
160*5f757f3fSDimitry Andric 
161*5f757f3fSDimitry Andric   IF->setTwoLevelNamespace(isTwoLevelNamespace());
162*5f757f3fSDimitry Andric   IF->setApplicationExtensionSafe(isApplicationExtensionSafe());
163*5f757f3fSDimitry Andric 
164*5f757f3fSDimitry Andric   for (const auto &It : umbrellas()) {
165*5f757f3fSDimitry Andric     if (!It.second.empty())
166*5f757f3fSDimitry Andric       IF->addParentUmbrella(It.first, It.second);
167*5f757f3fSDimitry Andric   }
168*5f757f3fSDimitry Andric   for (const auto &It : O->umbrellas()) {
169*5f757f3fSDimitry Andric     if (!It.second.empty())
170*5f757f3fSDimitry Andric       IF->addParentUmbrella(It.first, It.second);
171*5f757f3fSDimitry Andric   }
172*5f757f3fSDimitry Andric   IF->addTargets(targets());
173*5f757f3fSDimitry Andric   IF->addTargets(O->targets());
174*5f757f3fSDimitry Andric 
175*5f757f3fSDimitry Andric   for (const auto &Lib : allowableClients())
176*5f757f3fSDimitry Andric     for (const auto &Target : Lib.targets())
177*5f757f3fSDimitry Andric       IF->addAllowableClient(Lib.getInstallName(), Target);
178*5f757f3fSDimitry Andric 
179*5f757f3fSDimitry Andric   for (const auto &Lib : O->allowableClients())
180*5f757f3fSDimitry Andric     for (const auto &Target : Lib.targets())
181*5f757f3fSDimitry Andric       IF->addAllowableClient(Lib.getInstallName(), Target);
182*5f757f3fSDimitry Andric 
183*5f757f3fSDimitry Andric   for (const auto &Lib : reexportedLibraries())
184*5f757f3fSDimitry Andric     for (const auto &Target : Lib.targets())
185*5f757f3fSDimitry Andric       IF->addReexportedLibrary(Lib.getInstallName(), Target);
186*5f757f3fSDimitry Andric 
187*5f757f3fSDimitry Andric   for (const auto &Lib : O->reexportedLibraries())
188*5f757f3fSDimitry Andric     for (const auto &Target : Lib.targets())
189*5f757f3fSDimitry Andric       IF->addReexportedLibrary(Lib.getInstallName(), Target);
190*5f757f3fSDimitry Andric 
191*5f757f3fSDimitry Andric   for (const auto &[Target, Path] : rpaths())
192*5f757f3fSDimitry Andric     IF->addRPath(Target, Path);
193*5f757f3fSDimitry Andric   for (const auto &[Target, Path] : O->rpaths())
194*5f757f3fSDimitry Andric     IF->addRPath(Target, Path);
195*5f757f3fSDimitry Andric 
196*5f757f3fSDimitry Andric   for (const auto *Sym : symbols()) {
197*5f757f3fSDimitry Andric     IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(),
198*5f757f3fSDimitry Andric                   Sym->getFlags());
199*5f757f3fSDimitry Andric   }
200*5f757f3fSDimitry Andric 
201*5f757f3fSDimitry Andric   for (const auto *Sym : O->symbols()) {
202*5f757f3fSDimitry Andric     IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(),
203*5f757f3fSDimitry Andric                   Sym->getFlags());
204*5f757f3fSDimitry Andric   }
205*5f757f3fSDimitry Andric 
206*5f757f3fSDimitry Andric   return std::move(IF);
207*5f757f3fSDimitry Andric }
208*5f757f3fSDimitry Andric 
209*5f757f3fSDimitry Andric Expected<std::unique_ptr<InterfaceFile>>
210*5f757f3fSDimitry Andric InterfaceFile::remove(Architecture Arch) const {
211*5f757f3fSDimitry Andric   if (getArchitectures() == Arch)
212*5f757f3fSDimitry Andric     return make_error<StringError>("cannot remove last architecture slice '" +
213*5f757f3fSDimitry Andric                                        getArchitectureName(Arch) + "'",
214*5f757f3fSDimitry Andric                                    inconvertibleErrorCode());
215*5f757f3fSDimitry Andric 
216*5f757f3fSDimitry Andric   if (!getArchitectures().has(Arch)) {
217*5f757f3fSDimitry Andric     bool Found = false;
218*5f757f3fSDimitry Andric     for (auto &Doc : Documents) {
219*5f757f3fSDimitry Andric       if (Doc->getArchitectures().has(Arch)) {
220*5f757f3fSDimitry Andric         Found = true;
221*5f757f3fSDimitry Andric         break;
222*5f757f3fSDimitry Andric       }
223*5f757f3fSDimitry Andric     }
224*5f757f3fSDimitry Andric 
225*5f757f3fSDimitry Andric     if (!Found)
226*5f757f3fSDimitry Andric       return make_error<TextAPIError>(TextAPIErrorCode::NoSuchArchitecture);
227*5f757f3fSDimitry Andric   }
228*5f757f3fSDimitry Andric 
229*5f757f3fSDimitry Andric   std::unique_ptr<InterfaceFile> IF(new InterfaceFile());
230*5f757f3fSDimitry Andric   IF->setFileType(getFileType());
231*5f757f3fSDimitry Andric   IF->setPath(getPath());
232*5f757f3fSDimitry Andric   IF->addTargets(targets(ArchitectureSet::All().clear(Arch)));
233*5f757f3fSDimitry Andric   IF->setInstallName(getInstallName());
234*5f757f3fSDimitry Andric   IF->setCurrentVersion(getCurrentVersion());
235*5f757f3fSDimitry Andric   IF->setCompatibilityVersion(getCompatibilityVersion());
236*5f757f3fSDimitry Andric   IF->setSwiftABIVersion(getSwiftABIVersion());
237*5f757f3fSDimitry Andric   IF->setTwoLevelNamespace(isTwoLevelNamespace());
238*5f757f3fSDimitry Andric   IF->setApplicationExtensionSafe(isApplicationExtensionSafe());
239*5f757f3fSDimitry Andric   for (const auto &It : umbrellas())
240*5f757f3fSDimitry Andric     if (It.first.Arch != Arch)
241*5f757f3fSDimitry Andric       IF->addParentUmbrella(It.first, It.second);
242*5f757f3fSDimitry Andric 
243*5f757f3fSDimitry Andric   for (const auto &Lib : allowableClients()) {
244*5f757f3fSDimitry Andric     for (const auto &Target : Lib.targets())
245*5f757f3fSDimitry Andric       if (Target.Arch != Arch)
246*5f757f3fSDimitry Andric         IF->addAllowableClient(Lib.getInstallName(), Target);
247*5f757f3fSDimitry Andric   }
248*5f757f3fSDimitry Andric 
249*5f757f3fSDimitry Andric   for (const auto &Lib : reexportedLibraries()) {
250*5f757f3fSDimitry Andric     for (const auto &Target : Lib.targets())
251*5f757f3fSDimitry Andric       if (Target.Arch != Arch)
252*5f757f3fSDimitry Andric         IF->addReexportedLibrary(Lib.getInstallName(), Target);
253*5f757f3fSDimitry Andric   }
254*5f757f3fSDimitry Andric 
255*5f757f3fSDimitry Andric   for (const auto *Sym : symbols()) {
256*5f757f3fSDimitry Andric     auto Archs = Sym->getArchitectures();
257*5f757f3fSDimitry Andric     Archs.clear(Arch);
258*5f757f3fSDimitry Andric     if (Archs.empty())
259*5f757f3fSDimitry Andric       continue;
260*5f757f3fSDimitry Andric 
261*5f757f3fSDimitry Andric     IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(Archs),
262*5f757f3fSDimitry Andric                   Sym->getFlags());
263*5f757f3fSDimitry Andric   }
264*5f757f3fSDimitry Andric 
265*5f757f3fSDimitry Andric   for (auto &Doc : Documents) {
266*5f757f3fSDimitry Andric     // Skip the inlined document if the to be removed architecture is the
267*5f757f3fSDimitry Andric     // only one left.
268*5f757f3fSDimitry Andric     if (Doc->getArchitectures() == Arch)
269*5f757f3fSDimitry Andric       continue;
270*5f757f3fSDimitry Andric 
271*5f757f3fSDimitry Andric     // If the document doesn't contain the arch, then no work is to be done
272*5f757f3fSDimitry Andric     // and it can be copied over.
273*5f757f3fSDimitry Andric     if (!Doc->getArchitectures().has(Arch)) {
274*5f757f3fSDimitry Andric       auto NewDoc = Doc;
275*5f757f3fSDimitry Andric       IF->addDocument(std::move(NewDoc));
276*5f757f3fSDimitry Andric       continue;
277*5f757f3fSDimitry Andric     }
278*5f757f3fSDimitry Andric 
279*5f757f3fSDimitry Andric     auto Result = Doc->remove(Arch);
280*5f757f3fSDimitry Andric     if (!Result)
281*5f757f3fSDimitry Andric       return Result;
282*5f757f3fSDimitry Andric 
283*5f757f3fSDimitry Andric     IF->addDocument(std::move(Result.get()));
284*5f757f3fSDimitry Andric   }
285*5f757f3fSDimitry Andric 
286*5f757f3fSDimitry Andric   return std::move(IF);
287*5f757f3fSDimitry Andric }
288*5f757f3fSDimitry Andric 
289*5f757f3fSDimitry Andric Expected<std::unique_ptr<InterfaceFile>>
290*5f757f3fSDimitry Andric InterfaceFile::extract(Architecture Arch) const {
291*5f757f3fSDimitry Andric   if (!getArchitectures().has(Arch)) {
292*5f757f3fSDimitry Andric     return make_error<StringError>("file doesn't have architecture '" +
293*5f757f3fSDimitry Andric                                        getArchitectureName(Arch) + "'",
294*5f757f3fSDimitry Andric                                    inconvertibleErrorCode());
295*5f757f3fSDimitry Andric   }
296*5f757f3fSDimitry Andric 
297*5f757f3fSDimitry Andric   std::unique_ptr<InterfaceFile> IF(new InterfaceFile());
298*5f757f3fSDimitry Andric   IF->setFileType(getFileType());
299*5f757f3fSDimitry Andric   IF->setPath(getPath());
300*5f757f3fSDimitry Andric   IF->addTargets(targets(Arch));
301*5f757f3fSDimitry Andric   IF->setInstallName(getInstallName());
302*5f757f3fSDimitry Andric   IF->setCurrentVersion(getCurrentVersion());
303*5f757f3fSDimitry Andric   IF->setCompatibilityVersion(getCompatibilityVersion());
304*5f757f3fSDimitry Andric   IF->setSwiftABIVersion(getSwiftABIVersion());
305*5f757f3fSDimitry Andric   IF->setTwoLevelNamespace(isTwoLevelNamespace());
306*5f757f3fSDimitry Andric   IF->setApplicationExtensionSafe(isApplicationExtensionSafe());
307*5f757f3fSDimitry Andric   for (const auto &It : umbrellas())
308*5f757f3fSDimitry Andric     if (It.first.Arch == Arch)
309*5f757f3fSDimitry Andric       IF->addParentUmbrella(It.first, It.second);
310*5f757f3fSDimitry Andric 
311*5f757f3fSDimitry Andric   for (const auto &It : rpaths())
312*5f757f3fSDimitry Andric     if (It.first.Arch == Arch)
313*5f757f3fSDimitry Andric       IF->addRPath(It.first, It.second);
314*5f757f3fSDimitry Andric 
315*5f757f3fSDimitry Andric   for (const auto &Lib : allowableClients())
316*5f757f3fSDimitry Andric     for (const auto &Target : Lib.targets())
317*5f757f3fSDimitry Andric       if (Target.Arch == Arch)
318*5f757f3fSDimitry Andric         IF->addAllowableClient(Lib.getInstallName(), Target);
319*5f757f3fSDimitry Andric 
320*5f757f3fSDimitry Andric   for (const auto &Lib : reexportedLibraries())
321*5f757f3fSDimitry Andric     for (const auto &Target : Lib.targets())
322*5f757f3fSDimitry Andric       if (Target.Arch == Arch)
323*5f757f3fSDimitry Andric         IF->addReexportedLibrary(Lib.getInstallName(), Target);
324*5f757f3fSDimitry Andric 
325*5f757f3fSDimitry Andric   for (const auto *Sym : symbols()) {
326*5f757f3fSDimitry Andric     if (Sym->hasArchitecture(Arch))
327*5f757f3fSDimitry Andric       IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(Arch),
328*5f757f3fSDimitry Andric                     Sym->getFlags());
329*5f757f3fSDimitry Andric   }
330*5f757f3fSDimitry Andric 
331*5f757f3fSDimitry Andric   for (auto &Doc : Documents) {
332*5f757f3fSDimitry Andric     // Skip documents that don't have the requested architecture.
333*5f757f3fSDimitry Andric     if (!Doc->getArchitectures().has(Arch))
334*5f757f3fSDimitry Andric       continue;
335*5f757f3fSDimitry Andric 
336*5f757f3fSDimitry Andric     auto Result = Doc->extract(Arch);
337*5f757f3fSDimitry Andric     if (!Result)
338*5f757f3fSDimitry Andric       return Result;
339*5f757f3fSDimitry Andric 
340*5f757f3fSDimitry Andric     IF->addDocument(std::move(Result.get()));
341*5f757f3fSDimitry Andric   }
342*5f757f3fSDimitry Andric 
343*5f757f3fSDimitry Andric   return std::move(IF);
344*5f757f3fSDimitry Andric }
345*5f757f3fSDimitry Andric 
34606c3fb27SDimitry Andric static bool isYAMLTextStub(const FileType &Kind) {
34706c3fb27SDimitry Andric   return (Kind >= FileType::TBD_V1) && (Kind < FileType::TBD_V5);
34806c3fb27SDimitry Andric }
34906c3fb27SDimitry Andric 
350fe6060f1SDimitry Andric bool InterfaceFile::operator==(const InterfaceFile &O) const {
351fe6060f1SDimitry Andric   if (Targets != O.Targets)
352fe6060f1SDimitry Andric     return false;
353fe6060f1SDimitry Andric   if (InstallName != O.InstallName)
354fe6060f1SDimitry Andric     return false;
355fe6060f1SDimitry Andric   if ((CurrentVersion != O.CurrentVersion) ||
356fe6060f1SDimitry Andric       (CompatibilityVersion != O.CompatibilityVersion))
357fe6060f1SDimitry Andric     return false;
358fe6060f1SDimitry Andric   if (SwiftABIVersion != O.SwiftABIVersion)
359fe6060f1SDimitry Andric     return false;
360fe6060f1SDimitry Andric   if (IsTwoLevelNamespace != O.IsTwoLevelNamespace)
361fe6060f1SDimitry Andric     return false;
362fe6060f1SDimitry Andric   if (IsAppExtensionSafe != O.IsAppExtensionSafe)
363fe6060f1SDimitry Andric     return false;
364*5f757f3fSDimitry Andric   if (IsOSLibNotForSharedCache != O.IsOSLibNotForSharedCache)
365*5f757f3fSDimitry Andric     return false;
366*5f757f3fSDimitry Andric   if (HasSimSupport != O.HasSimSupport)
367*5f757f3fSDimitry Andric     return false;
368fe6060f1SDimitry Andric   if (ParentUmbrellas != O.ParentUmbrellas)
369fe6060f1SDimitry Andric     return false;
370fe6060f1SDimitry Andric   if (AllowableClients != O.AllowableClients)
371fe6060f1SDimitry Andric     return false;
372fe6060f1SDimitry Andric   if (ReexportedLibraries != O.ReexportedLibraries)
373fe6060f1SDimitry Andric     return false;
37406c3fb27SDimitry Andric   if (*SymbolsSet != *O.SymbolsSet)
375fe6060f1SDimitry Andric     return false;
37606c3fb27SDimitry Andric   // Don't compare run search paths for older filetypes that cannot express
37706c3fb27SDimitry Andric   // them.
37806c3fb27SDimitry Andric   if (!(isYAMLTextStub(FileKind)) && !(isYAMLTextStub(O.FileKind))) {
37906c3fb27SDimitry Andric     if (RPaths != O.RPaths)
38006c3fb27SDimitry Andric       return false;
38106c3fb27SDimitry Andric     if (mapToPlatformVersionSet(Targets) != mapToPlatformVersionSet(O.Targets))
38206c3fb27SDimitry Andric       return false;
38306c3fb27SDimitry Andric   }
38406c3fb27SDimitry Andric 
385fe6060f1SDimitry Andric   if (!std::equal(Documents.begin(), Documents.end(), O.Documents.begin(),
386fe6060f1SDimitry Andric                   O.Documents.end(),
387fe6060f1SDimitry Andric                   [](const std::shared_ptr<InterfaceFile> LHS,
388fe6060f1SDimitry Andric                      const std::shared_ptr<InterfaceFile> RHS) {
389fe6060f1SDimitry Andric                     return *LHS == *RHS;
390fe6060f1SDimitry Andric                   }))
391fe6060f1SDimitry Andric     return false;
392fe6060f1SDimitry Andric   return true;
393fe6060f1SDimitry Andric }
394