xref: /src/contrib/llvm-project/llvm/lib/TextAPI/InterfaceFile.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1e6d15924SDimitry Andric //===- InterfaceFile.cpp --------------------------------------------------===//
2e6d15924SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e6d15924SDimitry Andric //
7e6d15924SDimitry Andric //===----------------------------------------------------------------------===//
8e6d15924SDimitry Andric //
9e6d15924SDimitry Andric // Implements the Interface File.
10e6d15924SDimitry Andric //
11e6d15924SDimitry Andric //===----------------------------------------------------------------------===//
12e6d15924SDimitry Andric 
13344a3780SDimitry Andric #include "llvm/TextAPI/InterfaceFile.h"
14ac9a064cSDimitry Andric #include "llvm/TextAPI/RecordsSlice.h"
15b1c73532SDimitry Andric #include "llvm/TextAPI/TextAPIError.h"
16e6d15924SDimitry Andric #include <iomanip>
17e6d15924SDimitry Andric #include <sstream>
18e6d15924SDimitry Andric 
19cfca06d7SDimitry Andric using namespace llvm;
20cfca06d7SDimitry Andric using namespace llvm::MachO;
21cfca06d7SDimitry Andric 
addTarget(const Target & Target)221d5ae102SDimitry Andric void InterfaceFileRef::addTarget(const Target &Target) {
23cfca06d7SDimitry Andric   addEntry(Targets, Target);
241d5ae102SDimitry Andric }
251d5ae102SDimitry Andric 
addAllowableClient(StringRef InstallName,const Target & Target)261d5ae102SDimitry Andric void InterfaceFile::addAllowableClient(StringRef InstallName,
271d5ae102SDimitry Andric                                        const Target &Target) {
28950076cdSDimitry Andric   if (InstallName.empty())
29950076cdSDimitry Andric     return;
30cfca06d7SDimitry Andric   auto Client = addEntry(AllowableClients, InstallName);
311d5ae102SDimitry Andric   Client->addTarget(Target);
32e6d15924SDimitry Andric }
33e6d15924SDimitry Andric 
addReexportedLibrary(StringRef InstallName,const Target & Target)34e6d15924SDimitry Andric void InterfaceFile::addReexportedLibrary(StringRef InstallName,
351d5ae102SDimitry Andric                                          const Target &Target) {
36950076cdSDimitry Andric   if (InstallName.empty())
37950076cdSDimitry Andric     return;
38cfca06d7SDimitry Andric   auto Lib = addEntry(ReexportedLibraries, InstallName);
391d5ae102SDimitry Andric   Lib->addTarget(Target);
40e6d15924SDimitry Andric }
41e6d15924SDimitry Andric 
addParentUmbrella(const Target & Target_,StringRef Parent)421d5ae102SDimitry Andric void InterfaceFile::addParentUmbrella(const Target &Target_, StringRef Parent) {
43950076cdSDimitry Andric   if (Parent.empty())
44950076cdSDimitry Andric     return;
451d5ae102SDimitry Andric   auto Iter = lower_bound(ParentUmbrellas, Target_,
461d5ae102SDimitry Andric                           [](const std::pair<Target, std::string> &LHS,
471d5ae102SDimitry Andric                              Target RHS) { return LHS.first < RHS; });
48e6d15924SDimitry Andric 
491d5ae102SDimitry Andric   if ((Iter != ParentUmbrellas.end()) && !(Target_ < Iter->first)) {
50cfca06d7SDimitry Andric     Iter->second = std::string(Parent);
51e6d15924SDimitry Andric     return;
52e6d15924SDimitry Andric   }
53e6d15924SDimitry Andric 
54cfca06d7SDimitry Andric   ParentUmbrellas.emplace(Iter, Target_, std::string(Parent));
55e6d15924SDimitry Andric }
56e6d15924SDimitry Andric 
addRPath(StringRef RPath,const Target & InputTarget)57ac9a064cSDimitry Andric void InterfaceFile::addRPath(StringRef RPath, const Target &InputTarget) {
58950076cdSDimitry Andric   if (RPath.empty())
59950076cdSDimitry Andric     return;
60b1c73532SDimitry Andric   using RPathEntryT = const std::pair<Target, std::string>;
61b1c73532SDimitry Andric   RPathEntryT Entry(InputTarget, RPath);
62b1c73532SDimitry Andric   auto Iter =
63b1c73532SDimitry Andric       lower_bound(RPaths, Entry,
64b1c73532SDimitry Andric                   [](RPathEntryT &LHS, RPathEntryT &RHS) { return LHS < RHS; });
651d5ae102SDimitry Andric 
66b1c73532SDimitry Andric   if ((Iter != RPaths.end()) && (*Iter == Entry))
671d5ae102SDimitry Andric     return;
681d5ae102SDimitry Andric 
69b1c73532SDimitry Andric   RPaths.emplace(Iter, Entry);
701d5ae102SDimitry Andric }
711d5ae102SDimitry Andric 
addTarget(const Target & Target)721d5ae102SDimitry Andric void InterfaceFile::addTarget(const Target &Target) {
73cfca06d7SDimitry Andric   addEntry(Targets, Target);
741d5ae102SDimitry Andric }
751d5ae102SDimitry Andric 
761d5ae102SDimitry Andric InterfaceFile::const_filtered_target_range
targets(ArchitectureSet Archs) const771d5ae102SDimitry Andric InterfaceFile::targets(ArchitectureSet Archs) const {
781d5ae102SDimitry Andric   std::function<bool(const Target &)> fn = [Archs](const Target &Target_) {
791d5ae102SDimitry Andric     return Archs.has(Target_.Arch);
801d5ae102SDimitry Andric   };
811d5ae102SDimitry Andric   return make_filter_range(Targets, fn);
82e6d15924SDimitry Andric }
83e6d15924SDimitry Andric 
addDocument(std::shared_ptr<InterfaceFile> && Document)84344a3780SDimitry Andric void InterfaceFile::addDocument(std::shared_ptr<InterfaceFile> &&Document) {
85344a3780SDimitry Andric   auto Pos = llvm::lower_bound(Documents, Document,
86344a3780SDimitry Andric                                [](const std::shared_ptr<InterfaceFile> &LHS,
87344a3780SDimitry Andric                                   const std::shared_ptr<InterfaceFile> &RHS) {
88344a3780SDimitry Andric                                  return LHS->InstallName < RHS->InstallName;
89344a3780SDimitry Andric                                });
90344a3780SDimitry Andric   Document->Parent = this;
91344a3780SDimitry Andric   Documents.insert(Pos, Document);
92344a3780SDimitry Andric }
93344a3780SDimitry Andric 
inlineLibrary(std::shared_ptr<InterfaceFile> Library,bool Overwrite)94b1c73532SDimitry Andric void InterfaceFile::inlineLibrary(std::shared_ptr<InterfaceFile> Library,
95b1c73532SDimitry Andric                                   bool Overwrite) {
96b1c73532SDimitry Andric   auto AddFwk = [&](std::shared_ptr<InterfaceFile> &&Reexport) {
97b1c73532SDimitry Andric     auto It = lower_bound(
98b1c73532SDimitry Andric         Documents, Reexport->getInstallName(),
99b1c73532SDimitry Andric         [](std::shared_ptr<InterfaceFile> &Lhs, const StringRef Rhs) {
100b1c73532SDimitry Andric           return Lhs->getInstallName() < Rhs;
101b1c73532SDimitry Andric         });
102b1c73532SDimitry Andric 
103b1c73532SDimitry Andric     if (Overwrite && It != Documents.end() &&
104b1c73532SDimitry Andric         Reexport->getInstallName() == (*It)->getInstallName()) {
105b1c73532SDimitry Andric       std::replace(Documents.begin(), Documents.end(), *It,
106b1c73532SDimitry Andric                    std::move(Reexport));
107b1c73532SDimitry Andric       return;
108b1c73532SDimitry Andric     }
109b1c73532SDimitry Andric 
110b1c73532SDimitry Andric     if ((It != Documents.end()) &&
111b1c73532SDimitry Andric         !(Reexport->getInstallName() < (*It)->getInstallName()))
112b1c73532SDimitry Andric       return;
113b1c73532SDimitry Andric 
114b1c73532SDimitry Andric     Documents.emplace(It, std::move(Reexport));
115b1c73532SDimitry Andric   };
116b1c73532SDimitry Andric   for (auto Doc : Library->documents())
117b1c73532SDimitry Andric     AddFwk(std::move(Doc));
118b1c73532SDimitry Andric 
119b1c73532SDimitry Andric   Library->Documents.clear();
120b1c73532SDimitry Andric   AddFwk(std::move(Library));
121b1c73532SDimitry Andric }
122b1c73532SDimitry Andric 
123b1c73532SDimitry Andric Expected<std::unique_ptr<InterfaceFile>>
merge(const InterfaceFile * O) const124b1c73532SDimitry Andric InterfaceFile::merge(const InterfaceFile *O) const {
125b1c73532SDimitry Andric   // Verify files can be merged.
126b1c73532SDimitry Andric   if (getInstallName() != O->getInstallName()) {
127b1c73532SDimitry Andric     return make_error<StringError>("install names do not match",
128b1c73532SDimitry Andric                                    inconvertibleErrorCode());
129b1c73532SDimitry Andric   }
130b1c73532SDimitry Andric 
131b1c73532SDimitry Andric   if (getCurrentVersion() != O->getCurrentVersion()) {
132b1c73532SDimitry Andric     return make_error<StringError>("current versions do not match",
133b1c73532SDimitry Andric                                    inconvertibleErrorCode());
134b1c73532SDimitry Andric   }
135b1c73532SDimitry Andric 
136b1c73532SDimitry Andric   if (getCompatibilityVersion() != O->getCompatibilityVersion()) {
137b1c73532SDimitry Andric     return make_error<StringError>("compatibility versions do not match",
138b1c73532SDimitry Andric                                    inconvertibleErrorCode());
139b1c73532SDimitry Andric   }
140b1c73532SDimitry Andric 
141b1c73532SDimitry Andric   if ((getSwiftABIVersion() != 0) && (O->getSwiftABIVersion() != 0) &&
142b1c73532SDimitry Andric       (getSwiftABIVersion() != O->getSwiftABIVersion())) {
143b1c73532SDimitry Andric     return make_error<StringError>("swift ABI versions do not match",
144b1c73532SDimitry Andric                                    inconvertibleErrorCode());
145b1c73532SDimitry Andric   }
146b1c73532SDimitry Andric 
147b1c73532SDimitry Andric   if (isTwoLevelNamespace() != O->isTwoLevelNamespace()) {
148b1c73532SDimitry Andric     return make_error<StringError>("two level namespace flags do not match",
149b1c73532SDimitry Andric                                    inconvertibleErrorCode());
150b1c73532SDimitry Andric   }
151b1c73532SDimitry Andric 
152b1c73532SDimitry Andric   if (isApplicationExtensionSafe() != O->isApplicationExtensionSafe()) {
153b1c73532SDimitry Andric     return make_error<StringError>(
154b1c73532SDimitry Andric         "application extension safe flags do not match",
155b1c73532SDimitry Andric         inconvertibleErrorCode());
156b1c73532SDimitry Andric   }
157b1c73532SDimitry Andric 
158b1c73532SDimitry Andric   std::unique_ptr<InterfaceFile> IF(new InterfaceFile());
159b1c73532SDimitry Andric   IF->setFileType(std::max(getFileType(), O->getFileType()));
160b1c73532SDimitry Andric   IF->setPath(getPath());
161b1c73532SDimitry Andric   IF->setInstallName(getInstallName());
162b1c73532SDimitry Andric   IF->setCurrentVersion(getCurrentVersion());
163b1c73532SDimitry Andric   IF->setCompatibilityVersion(getCompatibilityVersion());
164b1c73532SDimitry Andric 
165b1c73532SDimitry Andric   if (getSwiftABIVersion() == 0)
166b1c73532SDimitry Andric     IF->setSwiftABIVersion(O->getSwiftABIVersion());
167b1c73532SDimitry Andric   else
168b1c73532SDimitry Andric     IF->setSwiftABIVersion(getSwiftABIVersion());
169b1c73532SDimitry Andric 
170b1c73532SDimitry Andric   IF->setTwoLevelNamespace(isTwoLevelNamespace());
171b1c73532SDimitry Andric   IF->setApplicationExtensionSafe(isApplicationExtensionSafe());
172b1c73532SDimitry Andric 
173b1c73532SDimitry Andric   for (const auto &It : umbrellas()) {
174b1c73532SDimitry Andric     if (!It.second.empty())
175b1c73532SDimitry Andric       IF->addParentUmbrella(It.first, It.second);
176b1c73532SDimitry Andric   }
177b1c73532SDimitry Andric   for (const auto &It : O->umbrellas()) {
178b1c73532SDimitry Andric     if (!It.second.empty())
179b1c73532SDimitry Andric       IF->addParentUmbrella(It.first, It.second);
180b1c73532SDimitry Andric   }
181b1c73532SDimitry Andric   IF->addTargets(targets());
182b1c73532SDimitry Andric   IF->addTargets(O->targets());
183b1c73532SDimitry Andric 
184b1c73532SDimitry Andric   for (const auto &Lib : allowableClients())
185b1c73532SDimitry Andric     for (const auto &Target : Lib.targets())
186b1c73532SDimitry Andric       IF->addAllowableClient(Lib.getInstallName(), Target);
187b1c73532SDimitry Andric 
188b1c73532SDimitry Andric   for (const auto &Lib : O->allowableClients())
189b1c73532SDimitry Andric     for (const auto &Target : Lib.targets())
190b1c73532SDimitry Andric       IF->addAllowableClient(Lib.getInstallName(), Target);
191b1c73532SDimitry Andric 
192b1c73532SDimitry Andric   for (const auto &Lib : reexportedLibraries())
193b1c73532SDimitry Andric     for (const auto &Target : Lib.targets())
194b1c73532SDimitry Andric       IF->addReexportedLibrary(Lib.getInstallName(), Target);
195b1c73532SDimitry Andric 
196b1c73532SDimitry Andric   for (const auto &Lib : O->reexportedLibraries())
197b1c73532SDimitry Andric     for (const auto &Target : Lib.targets())
198b1c73532SDimitry Andric       IF->addReexportedLibrary(Lib.getInstallName(), Target);
199b1c73532SDimitry Andric 
200b1c73532SDimitry Andric   for (const auto &[Target, Path] : rpaths())
201ac9a064cSDimitry Andric     IF->addRPath(Path, Target);
202b1c73532SDimitry Andric   for (const auto &[Target, Path] : O->rpaths())
203ac9a064cSDimitry Andric     IF->addRPath(Path, Target);
204b1c73532SDimitry Andric 
205b1c73532SDimitry Andric   for (const auto *Sym : symbols()) {
206b1c73532SDimitry Andric     IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(),
207b1c73532SDimitry Andric                   Sym->getFlags());
208b1c73532SDimitry Andric   }
209b1c73532SDimitry Andric 
210b1c73532SDimitry Andric   for (const auto *Sym : O->symbols()) {
211b1c73532SDimitry Andric     IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(),
212b1c73532SDimitry Andric                   Sym->getFlags());
213b1c73532SDimitry Andric   }
214b1c73532SDimitry Andric 
215b1c73532SDimitry Andric   return std::move(IF);
216b1c73532SDimitry Andric }
217b1c73532SDimitry Andric 
218b1c73532SDimitry Andric Expected<std::unique_ptr<InterfaceFile>>
remove(Architecture Arch) const219b1c73532SDimitry Andric InterfaceFile::remove(Architecture Arch) const {
220b1c73532SDimitry Andric   if (getArchitectures() == Arch)
221b1c73532SDimitry Andric     return make_error<StringError>("cannot remove last architecture slice '" +
222b1c73532SDimitry Andric                                        getArchitectureName(Arch) + "'",
223b1c73532SDimitry Andric                                    inconvertibleErrorCode());
224b1c73532SDimitry Andric 
225b1c73532SDimitry Andric   if (!getArchitectures().has(Arch)) {
226b1c73532SDimitry Andric     bool Found = false;
227b1c73532SDimitry Andric     for (auto &Doc : Documents) {
228b1c73532SDimitry Andric       if (Doc->getArchitectures().has(Arch)) {
229b1c73532SDimitry Andric         Found = true;
230b1c73532SDimitry Andric         break;
231b1c73532SDimitry Andric       }
232b1c73532SDimitry Andric     }
233b1c73532SDimitry Andric 
234b1c73532SDimitry Andric     if (!Found)
235b1c73532SDimitry Andric       return make_error<TextAPIError>(TextAPIErrorCode::NoSuchArchitecture);
236b1c73532SDimitry Andric   }
237b1c73532SDimitry Andric 
238b1c73532SDimitry Andric   std::unique_ptr<InterfaceFile> IF(new InterfaceFile());
239b1c73532SDimitry Andric   IF->setFileType(getFileType());
240b1c73532SDimitry Andric   IF->setPath(getPath());
241b1c73532SDimitry Andric   IF->addTargets(targets(ArchitectureSet::All().clear(Arch)));
242b1c73532SDimitry Andric   IF->setInstallName(getInstallName());
243b1c73532SDimitry Andric   IF->setCurrentVersion(getCurrentVersion());
244b1c73532SDimitry Andric   IF->setCompatibilityVersion(getCompatibilityVersion());
245b1c73532SDimitry Andric   IF->setSwiftABIVersion(getSwiftABIVersion());
246b1c73532SDimitry Andric   IF->setTwoLevelNamespace(isTwoLevelNamespace());
247b1c73532SDimitry Andric   IF->setApplicationExtensionSafe(isApplicationExtensionSafe());
248b1c73532SDimitry Andric   for (const auto &It : umbrellas())
249b1c73532SDimitry Andric     if (It.first.Arch != Arch)
250b1c73532SDimitry Andric       IF->addParentUmbrella(It.first, It.second);
251b1c73532SDimitry Andric 
252b1c73532SDimitry Andric   for (const auto &Lib : allowableClients()) {
253b1c73532SDimitry Andric     for (const auto &Target : Lib.targets())
254b1c73532SDimitry Andric       if (Target.Arch != Arch)
255b1c73532SDimitry Andric         IF->addAllowableClient(Lib.getInstallName(), Target);
256b1c73532SDimitry Andric   }
257b1c73532SDimitry Andric 
258b1c73532SDimitry Andric   for (const auto &Lib : reexportedLibraries()) {
259b1c73532SDimitry Andric     for (const auto &Target : Lib.targets())
260b1c73532SDimitry Andric       if (Target.Arch != Arch)
261b1c73532SDimitry Andric         IF->addReexportedLibrary(Lib.getInstallName(), Target);
262b1c73532SDimitry Andric   }
263b1c73532SDimitry Andric 
264b1c73532SDimitry Andric   for (const auto *Sym : symbols()) {
265b1c73532SDimitry Andric     auto Archs = Sym->getArchitectures();
266b1c73532SDimitry Andric     Archs.clear(Arch);
267b1c73532SDimitry Andric     if (Archs.empty())
268b1c73532SDimitry Andric       continue;
269b1c73532SDimitry Andric 
270b1c73532SDimitry Andric     IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(Archs),
271b1c73532SDimitry Andric                   Sym->getFlags());
272b1c73532SDimitry Andric   }
273b1c73532SDimitry Andric 
274b1c73532SDimitry Andric   for (auto &Doc : Documents) {
275b1c73532SDimitry Andric     // Skip the inlined document if the to be removed architecture is the
276b1c73532SDimitry Andric     // only one left.
277b1c73532SDimitry Andric     if (Doc->getArchitectures() == Arch)
278b1c73532SDimitry Andric       continue;
279b1c73532SDimitry Andric 
280b1c73532SDimitry Andric     // If the document doesn't contain the arch, then no work is to be done
281b1c73532SDimitry Andric     // and it can be copied over.
282b1c73532SDimitry Andric     if (!Doc->getArchitectures().has(Arch)) {
283b1c73532SDimitry Andric       auto NewDoc = Doc;
284b1c73532SDimitry Andric       IF->addDocument(std::move(NewDoc));
285b1c73532SDimitry Andric       continue;
286b1c73532SDimitry Andric     }
287b1c73532SDimitry Andric 
288b1c73532SDimitry Andric     auto Result = Doc->remove(Arch);
289b1c73532SDimitry Andric     if (!Result)
290b1c73532SDimitry Andric       return Result;
291b1c73532SDimitry Andric 
292b1c73532SDimitry Andric     IF->addDocument(std::move(Result.get()));
293b1c73532SDimitry Andric   }
294b1c73532SDimitry Andric 
295b1c73532SDimitry Andric   return std::move(IF);
296b1c73532SDimitry Andric }
297b1c73532SDimitry Andric 
298b1c73532SDimitry Andric Expected<std::unique_ptr<InterfaceFile>>
extract(Architecture Arch) const299b1c73532SDimitry Andric InterfaceFile::extract(Architecture Arch) const {
300b1c73532SDimitry Andric   if (!getArchitectures().has(Arch)) {
301b1c73532SDimitry Andric     return make_error<StringError>("file doesn't have architecture '" +
302b1c73532SDimitry Andric                                        getArchitectureName(Arch) + "'",
303b1c73532SDimitry Andric                                    inconvertibleErrorCode());
304b1c73532SDimitry Andric   }
305b1c73532SDimitry Andric 
306b1c73532SDimitry Andric   std::unique_ptr<InterfaceFile> IF(new InterfaceFile());
307b1c73532SDimitry Andric   IF->setFileType(getFileType());
308b1c73532SDimitry Andric   IF->setPath(getPath());
309b1c73532SDimitry Andric   IF->addTargets(targets(Arch));
310b1c73532SDimitry Andric   IF->setInstallName(getInstallName());
311b1c73532SDimitry Andric   IF->setCurrentVersion(getCurrentVersion());
312b1c73532SDimitry Andric   IF->setCompatibilityVersion(getCompatibilityVersion());
313b1c73532SDimitry Andric   IF->setSwiftABIVersion(getSwiftABIVersion());
314b1c73532SDimitry Andric   IF->setTwoLevelNamespace(isTwoLevelNamespace());
315b1c73532SDimitry Andric   IF->setApplicationExtensionSafe(isApplicationExtensionSafe());
316b1c73532SDimitry Andric   for (const auto &It : umbrellas())
317b1c73532SDimitry Andric     if (It.first.Arch == Arch)
318b1c73532SDimitry Andric       IF->addParentUmbrella(It.first, It.second);
319b1c73532SDimitry Andric 
320b1c73532SDimitry Andric   for (const auto &It : rpaths())
321b1c73532SDimitry Andric     if (It.first.Arch == Arch)
322ac9a064cSDimitry Andric       IF->addRPath(It.second, It.first);
323b1c73532SDimitry Andric 
324b1c73532SDimitry Andric   for (const auto &Lib : allowableClients())
325b1c73532SDimitry Andric     for (const auto &Target : Lib.targets())
326b1c73532SDimitry Andric       if (Target.Arch == Arch)
327b1c73532SDimitry Andric         IF->addAllowableClient(Lib.getInstallName(), Target);
328b1c73532SDimitry Andric 
329b1c73532SDimitry Andric   for (const auto &Lib : reexportedLibraries())
330b1c73532SDimitry Andric     for (const auto &Target : Lib.targets())
331b1c73532SDimitry Andric       if (Target.Arch == Arch)
332b1c73532SDimitry Andric         IF->addReexportedLibrary(Lib.getInstallName(), Target);
333b1c73532SDimitry Andric 
334b1c73532SDimitry Andric   for (const auto *Sym : symbols()) {
335b1c73532SDimitry Andric     if (Sym->hasArchitecture(Arch))
336b1c73532SDimitry Andric       IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(Arch),
337b1c73532SDimitry Andric                     Sym->getFlags());
338b1c73532SDimitry Andric   }
339b1c73532SDimitry Andric 
340b1c73532SDimitry Andric   for (auto &Doc : Documents) {
341b1c73532SDimitry Andric     // Skip documents that don't have the requested architecture.
342b1c73532SDimitry Andric     if (!Doc->getArchitectures().has(Arch))
343b1c73532SDimitry Andric       continue;
344b1c73532SDimitry Andric 
345b1c73532SDimitry Andric     auto Result = Doc->extract(Arch);
346b1c73532SDimitry Andric     if (!Result)
347b1c73532SDimitry Andric       return Result;
348b1c73532SDimitry Andric 
349b1c73532SDimitry Andric     IF->addDocument(std::move(Result.get()));
350b1c73532SDimitry Andric   }
351b1c73532SDimitry Andric 
352b1c73532SDimitry Andric   return std::move(IF);
353b1c73532SDimitry Andric }
354b1c73532SDimitry Andric 
setFromBinaryAttrs(const RecordsSlice::BinaryAttrs & BA,const Target & Targ)355ac9a064cSDimitry Andric void InterfaceFile::setFromBinaryAttrs(const RecordsSlice::BinaryAttrs &BA,
356ac9a064cSDimitry Andric                                        const Target &Targ) {
357ac9a064cSDimitry Andric   if (getFileType() != BA.File)
358ac9a064cSDimitry Andric     setFileType(BA.File);
359ac9a064cSDimitry Andric   if (getInstallName().empty())
360ac9a064cSDimitry Andric     setInstallName(BA.InstallName);
361ac9a064cSDimitry Andric   if (BA.AppExtensionSafe && !isApplicationExtensionSafe())
362ac9a064cSDimitry Andric     setApplicationExtensionSafe();
363ac9a064cSDimitry Andric   if (BA.TwoLevelNamespace && !isTwoLevelNamespace())
364ac9a064cSDimitry Andric     setTwoLevelNamespace();
365ac9a064cSDimitry Andric   if (BA.OSLibNotForSharedCache && !isOSLibNotForSharedCache())
366ac9a064cSDimitry Andric     setOSLibNotForSharedCache();
367ac9a064cSDimitry Andric   if (getCurrentVersion().empty())
368ac9a064cSDimitry Andric     setCurrentVersion(BA.CurrentVersion);
369ac9a064cSDimitry Andric   if (getCompatibilityVersion().empty())
370ac9a064cSDimitry Andric     setCompatibilityVersion(BA.CompatVersion);
371ac9a064cSDimitry Andric   if (getSwiftABIVersion() == 0)
372ac9a064cSDimitry Andric     setSwiftABIVersion(BA.SwiftABI);
373ac9a064cSDimitry Andric   if (getPath().empty())
374ac9a064cSDimitry Andric     setPath(BA.Path);
375ac9a064cSDimitry Andric   if (!BA.ParentUmbrella.empty())
376ac9a064cSDimitry Andric     addParentUmbrella(Targ, BA.ParentUmbrella);
377ac9a064cSDimitry Andric   for (const auto &Client : BA.AllowableClients)
378ac9a064cSDimitry Andric     addAllowableClient(Client, Targ);
379ac9a064cSDimitry Andric   for (const auto &Lib : BA.RexportedLibraries)
380ac9a064cSDimitry Andric     addReexportedLibrary(Lib, Targ);
381ac9a064cSDimitry Andric }
382ac9a064cSDimitry Andric 
isYAMLTextStub(const FileType & Kind)3837fa27ce4SDimitry Andric static bool isYAMLTextStub(const FileType &Kind) {
3847fa27ce4SDimitry Andric   return (Kind >= FileType::TBD_V1) && (Kind < FileType::TBD_V5);
3857fa27ce4SDimitry Andric }
3867fa27ce4SDimitry Andric 
operator ==(const InterfaceFile & O) const387344a3780SDimitry Andric bool InterfaceFile::operator==(const InterfaceFile &O) const {
388344a3780SDimitry Andric   if (Targets != O.Targets)
389344a3780SDimitry Andric     return false;
390344a3780SDimitry Andric   if (InstallName != O.InstallName)
391344a3780SDimitry Andric     return false;
392344a3780SDimitry Andric   if ((CurrentVersion != O.CurrentVersion) ||
393344a3780SDimitry Andric       (CompatibilityVersion != O.CompatibilityVersion))
394344a3780SDimitry Andric     return false;
395344a3780SDimitry Andric   if (SwiftABIVersion != O.SwiftABIVersion)
396344a3780SDimitry Andric     return false;
397344a3780SDimitry Andric   if (IsTwoLevelNamespace != O.IsTwoLevelNamespace)
398344a3780SDimitry Andric     return false;
399344a3780SDimitry Andric   if (IsAppExtensionSafe != O.IsAppExtensionSafe)
400344a3780SDimitry Andric     return false;
401b1c73532SDimitry Andric   if (IsOSLibNotForSharedCache != O.IsOSLibNotForSharedCache)
402b1c73532SDimitry Andric     return false;
403b1c73532SDimitry Andric   if (HasSimSupport != O.HasSimSupport)
404b1c73532SDimitry Andric     return false;
405344a3780SDimitry Andric   if (ParentUmbrellas != O.ParentUmbrellas)
406344a3780SDimitry Andric     return false;
407344a3780SDimitry Andric   if (AllowableClients != O.AllowableClients)
408344a3780SDimitry Andric     return false;
409344a3780SDimitry Andric   if (ReexportedLibraries != O.ReexportedLibraries)
410344a3780SDimitry Andric     return false;
4117fa27ce4SDimitry Andric   if (*SymbolsSet != *O.SymbolsSet)
412344a3780SDimitry Andric     return false;
4137fa27ce4SDimitry Andric   // Don't compare run search paths for older filetypes that cannot express
4147fa27ce4SDimitry Andric   // them.
4157fa27ce4SDimitry Andric   if (!(isYAMLTextStub(FileKind)) && !(isYAMLTextStub(O.FileKind))) {
4167fa27ce4SDimitry Andric     if (RPaths != O.RPaths)
4177fa27ce4SDimitry Andric       return false;
4187fa27ce4SDimitry Andric     if (mapToPlatformVersionSet(Targets) != mapToPlatformVersionSet(O.Targets))
4197fa27ce4SDimitry Andric       return false;
4207fa27ce4SDimitry Andric   }
4217fa27ce4SDimitry Andric 
422344a3780SDimitry Andric   if (!std::equal(Documents.begin(), Documents.end(), O.Documents.begin(),
423344a3780SDimitry Andric                   O.Documents.end(),
424344a3780SDimitry Andric                   [](const std::shared_ptr<InterfaceFile> LHS,
425344a3780SDimitry Andric                      const std::shared_ptr<InterfaceFile> RHS) {
426344a3780SDimitry Andric                     return *LHS == *RHS;
427344a3780SDimitry Andric                   }))
428344a3780SDimitry Andric     return false;
429344a3780SDimitry Andric   return true;
430344a3780SDimitry Andric }
431