xref: /src/contrib/llvm-project/llvm/lib/TextAPI/RecordsSlice.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1b1c73532SDimitry Andric //===- RecordsSlice.cpp --------------------------------------------------===//
2b1c73532SDimitry Andric //
3b1c73532SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b1c73532SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5b1c73532SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b1c73532SDimitry Andric //
7b1c73532SDimitry Andric //===----------------------------------------------------------------------===//
8b1c73532SDimitry Andric //
9b1c73532SDimitry Andric // Implements the Records Slice APIs.
10b1c73532SDimitry Andric //
11b1c73532SDimitry Andric //===----------------------------------------------------------------------===//
12b1c73532SDimitry Andric 
13b1c73532SDimitry Andric #include "llvm/TextAPI/RecordsSlice.h"
1499aabd70SDimitry Andric #include "llvm/ADT/SetVector.h"
15ac9a064cSDimitry Andric #include "llvm/TextAPI/InterfaceFile.h"
16b1c73532SDimitry Andric #include "llvm/TextAPI/Record.h"
17b1c73532SDimitry Andric #include "llvm/TextAPI/Symbol.h"
18b1c73532SDimitry Andric #include <utility>
19b1c73532SDimitry Andric 
20b1c73532SDimitry Andric using namespace llvm;
21b1c73532SDimitry Andric using namespace llvm::MachO;
22b1c73532SDimitry Andric 
addRecord(StringRef Name,SymbolFlags Flags,GlobalRecord::Kind GV,RecordLinkage Linkage)23b1c73532SDimitry Andric Record *RecordsSlice::addRecord(StringRef Name, SymbolFlags Flags,
24b1c73532SDimitry Andric                                 GlobalRecord::Kind GV, RecordLinkage Linkage) {
25b1c73532SDimitry Andric   // Find a specific Record type to capture.
26ac9a064cSDimitry Andric   auto [APIName, SymKind, InterfaceType] = parseSymbol(Name);
27b1c73532SDimitry Andric   Name = APIName;
28b1c73532SDimitry Andric   switch (SymKind) {
29ac9a064cSDimitry Andric   case EncodeKind::GlobalSymbol:
30b1c73532SDimitry Andric     return addGlobal(Name, Linkage, GV, Flags);
31ac9a064cSDimitry Andric   case EncodeKind::ObjectiveCClass:
32ac9a064cSDimitry Andric     return addObjCInterface(Name, Linkage, InterfaceType);
33ac9a064cSDimitry Andric   case EncodeKind::ObjectiveCClassEHType: {
34ac9a064cSDimitry Andric     ObjCInterfaceRecord *Rec = addObjCInterface(Name, Linkage, InterfaceType);
35ac9a064cSDimitry Andric     // When classes without ehtype are used in try/catch blocks
36ac9a064cSDimitry Andric     // a weak-defined symbol is exported.
37ac9a064cSDimitry Andric     if ((Flags & SymbolFlags::WeakDefined) == SymbolFlags::WeakDefined)
38ac9a064cSDimitry Andric       updateFlags(Rec, SymbolFlags::WeakDefined);
39ac9a064cSDimitry Andric     return Rec;
40ac9a064cSDimitry Andric   }
41ac9a064cSDimitry Andric   case EncodeKind::ObjectiveCInstanceVariable: {
42b1c73532SDimitry Andric     auto [Super, IVar] = Name.split('.');
43b1c73532SDimitry Andric     // Attempt to find super class.
44b1c73532SDimitry Andric     ObjCContainerRecord *Container = findContainer(/*isIVar=*/false, Super);
45b1c73532SDimitry Andric     // If not found, create extension since there is no mapped class symbol.
46b1c73532SDimitry Andric     if (Container == nullptr)
47b1c73532SDimitry Andric       Container = addObjCCategory(Super, {});
48b1c73532SDimitry Andric     return addObjCIVar(Container, IVar, Linkage);
49b1c73532SDimitry Andric   }
50b1c73532SDimitry Andric   }
51b1c73532SDimitry Andric 
52b1c73532SDimitry Andric   llvm_unreachable("unexpected symbol kind when adding to Record Slice");
53b1c73532SDimitry Andric }
54b1c73532SDimitry Andric 
findContainer(bool IsIVar,StringRef Name) const55b1c73532SDimitry Andric ObjCContainerRecord *RecordsSlice::findContainer(bool IsIVar,
56b1c73532SDimitry Andric                                                  StringRef Name) const {
57b1c73532SDimitry Andric   StringRef Super = IsIVar ? Name.split('.').first : Name;
58b1c73532SDimitry Andric   ObjCContainerRecord *Container = findObjCInterface(Super);
59b1c73532SDimitry Andric   // Ivars can only exist with extensions, if they did not come from
60b1c73532SDimitry Andric   // class.
61b1c73532SDimitry Andric   if (Container == nullptr)
62b1c73532SDimitry Andric     Container = findObjCCategory(Super, "");
63b1c73532SDimitry Andric   return Container;
64b1c73532SDimitry Andric }
65b1c73532SDimitry Andric 
66b1c73532SDimitry Andric template <typename R, typename C = RecordMap<R>, typename K = StringRef>
findRecord(K Key,const C & Container)67b1c73532SDimitry Andric R *findRecord(K Key, const C &Container) {
68b1c73532SDimitry Andric   const auto *Record = Container.find(Key);
69b1c73532SDimitry Andric   if (Record == Container.end())
70b1c73532SDimitry Andric     return nullptr;
71b1c73532SDimitry Andric   return Record->second.get();
72b1c73532SDimitry Andric }
73b1c73532SDimitry Andric 
findGlobal(StringRef Name,GlobalRecord::Kind GV) const74b1c73532SDimitry Andric GlobalRecord *RecordsSlice::findGlobal(StringRef Name,
75b1c73532SDimitry Andric                                        GlobalRecord::Kind GV) const {
76b1c73532SDimitry Andric   auto *Record = findRecord<GlobalRecord>(Name, Globals);
77b1c73532SDimitry Andric   if (!Record)
78b1c73532SDimitry Andric     return nullptr;
79b1c73532SDimitry Andric 
80b1c73532SDimitry Andric   switch (GV) {
81b1c73532SDimitry Andric   case GlobalRecord::Kind::Variable: {
82b1c73532SDimitry Andric     if (!Record->isVariable())
83b1c73532SDimitry Andric       return nullptr;
84b1c73532SDimitry Andric     break;
85b1c73532SDimitry Andric   }
86b1c73532SDimitry Andric   case GlobalRecord::Kind::Function: {
87b1c73532SDimitry Andric     if (!Record->isFunction())
88b1c73532SDimitry Andric       return nullptr;
89b1c73532SDimitry Andric     break;
90b1c73532SDimitry Andric   }
91b1c73532SDimitry Andric   case GlobalRecord::Kind::Unknown:
92b1c73532SDimitry Andric     return Record;
93b1c73532SDimitry Andric   }
94b1c73532SDimitry Andric 
95b1c73532SDimitry Andric   return Record;
96b1c73532SDimitry Andric }
97b1c73532SDimitry Andric 
98ac9a064cSDimitry Andric RecordLinkage
getLinkageForSymbol(ObjCIFSymbolKind CurrType) const99ac9a064cSDimitry Andric ObjCInterfaceRecord::getLinkageForSymbol(ObjCIFSymbolKind CurrType) const {
100ac9a064cSDimitry Andric   assert(CurrType <= ObjCIFSymbolKind::EHType &&
101ac9a064cSDimitry Andric          "expected single ObjCIFSymbolKind enum value");
102ac9a064cSDimitry Andric   if (CurrType == ObjCIFSymbolKind::Class)
103ac9a064cSDimitry Andric     return Linkages.Class;
104ac9a064cSDimitry Andric 
105ac9a064cSDimitry Andric   if (CurrType == ObjCIFSymbolKind::MetaClass)
106ac9a064cSDimitry Andric     return Linkages.MetaClass;
107ac9a064cSDimitry Andric 
108ac9a064cSDimitry Andric   if (CurrType == ObjCIFSymbolKind::EHType)
109ac9a064cSDimitry Andric     return Linkages.EHType;
110ac9a064cSDimitry Andric 
111ac9a064cSDimitry Andric   llvm_unreachable("unexpected ObjCIFSymbolKind");
112ac9a064cSDimitry Andric }
113ac9a064cSDimitry Andric 
updateLinkageForSymbols(ObjCIFSymbolKind SymType,RecordLinkage Link)114ac9a064cSDimitry Andric void ObjCInterfaceRecord::updateLinkageForSymbols(ObjCIFSymbolKind SymType,
115ac9a064cSDimitry Andric                                                   RecordLinkage Link) {
116ac9a064cSDimitry Andric   if ((SymType & ObjCIFSymbolKind::Class) == ObjCIFSymbolKind::Class)
117ac9a064cSDimitry Andric     Linkages.Class = std::max(Link, Linkages.Class);
118ac9a064cSDimitry Andric   if ((SymType & ObjCIFSymbolKind::MetaClass) == ObjCIFSymbolKind::MetaClass)
119ac9a064cSDimitry Andric     Linkages.MetaClass = std::max(Link, Linkages.MetaClass);
120ac9a064cSDimitry Andric   if ((SymType & ObjCIFSymbolKind::EHType) == ObjCIFSymbolKind::EHType)
121ac9a064cSDimitry Andric     Linkages.EHType = std::max(Link, Linkages.EHType);
122ac9a064cSDimitry Andric 
123ac9a064cSDimitry Andric   // Obj-C Classes represent multiple symbols that could have competing
124ac9a064cSDimitry Andric   // linkages, in this case assign the largest one, when querying the linkage of
125ac9a064cSDimitry Andric   // the record itself. This allows visitors pick whether they want to account
126ac9a064cSDimitry Andric   // for complete symbol information.
127ac9a064cSDimitry Andric   Linkage =
128ac9a064cSDimitry Andric       std::max(Linkages.Class, std::max(Linkages.MetaClass, Linkages.EHType));
129ac9a064cSDimitry Andric }
130ac9a064cSDimitry Andric 
findObjCInterface(StringRef Name) const131b1c73532SDimitry Andric ObjCInterfaceRecord *RecordsSlice::findObjCInterface(StringRef Name) const {
132b1c73532SDimitry Andric   return findRecord<ObjCInterfaceRecord>(Name, Classes);
133b1c73532SDimitry Andric }
134b1c73532SDimitry Andric 
findObjCCategory(StringRef ClassToExtend,StringRef Category) const135b1c73532SDimitry Andric ObjCCategoryRecord *RecordsSlice::findObjCCategory(StringRef ClassToExtend,
136b1c73532SDimitry Andric                                                    StringRef Category) const {
137b1c73532SDimitry Andric   return findRecord<ObjCCategoryRecord>(std::make_pair(ClassToExtend, Category),
138b1c73532SDimitry Andric                                         Categories);
139b1c73532SDimitry Andric }
140b1c73532SDimitry Andric 
findObjCIVar(StringRef IVar) const141b1c73532SDimitry Andric ObjCIVarRecord *ObjCContainerRecord::findObjCIVar(StringRef IVar) const {
142b1c73532SDimitry Andric   return findRecord<ObjCIVarRecord>(IVar, IVars);
143b1c73532SDimitry Andric }
144b1c73532SDimitry Andric 
findObjCIVar(bool IsScopedName,StringRef Name) const145b1c73532SDimitry Andric ObjCIVarRecord *RecordsSlice::findObjCIVar(bool IsScopedName,
146b1c73532SDimitry Andric                                            StringRef Name) const {
147b1c73532SDimitry Andric   // If scoped name, the name of the container is known.
148b1c73532SDimitry Andric   if (IsScopedName) {
149b1c73532SDimitry Andric     // IVar does not exist if there is not a container assigned to it.
150b1c73532SDimitry Andric     auto *Container = findContainer(/*IsIVar=*/true, Name);
151b1c73532SDimitry Andric     if (!Container)
152b1c73532SDimitry Andric       return nullptr;
153b1c73532SDimitry Andric 
154b1c73532SDimitry Andric     StringRef IVar = Name.substr(Name.find_first_of('.') + 1);
155b1c73532SDimitry Andric     return Container->findObjCIVar(IVar);
156b1c73532SDimitry Andric   }
157b1c73532SDimitry Andric 
158b1c73532SDimitry Andric   // Otherwise traverse through containers and attempt to find IVar.
159b1c73532SDimitry Andric   auto getIVar = [Name](auto &Records) -> ObjCIVarRecord * {
160b1c73532SDimitry Andric     for (const auto &[_, Container] : Records) {
161b1c73532SDimitry Andric       if (auto *IVarR = Container->findObjCIVar(Name))
162b1c73532SDimitry Andric         return IVarR;
163b1c73532SDimitry Andric     }
164b1c73532SDimitry Andric     return nullptr;
165b1c73532SDimitry Andric   };
166b1c73532SDimitry Andric 
167b1c73532SDimitry Andric   if (auto *IVarRecord = getIVar(Classes))
168b1c73532SDimitry Andric     return IVarRecord;
169b1c73532SDimitry Andric 
170b1c73532SDimitry Andric   return getIVar(Categories);
171b1c73532SDimitry Andric }
172b1c73532SDimitry Andric 
addGlobal(StringRef Name,RecordLinkage Linkage,GlobalRecord::Kind GV,SymbolFlags Flags,bool Inlined)173b1c73532SDimitry Andric GlobalRecord *RecordsSlice::addGlobal(StringRef Name, RecordLinkage Linkage,
174ac9a064cSDimitry Andric                                       GlobalRecord::Kind GV, SymbolFlags Flags,
175ac9a064cSDimitry Andric                                       bool Inlined) {
176b1c73532SDimitry Andric   if (GV == GlobalRecord::Kind::Function)
177b1c73532SDimitry Andric     Flags |= SymbolFlags::Text;
178b1c73532SDimitry Andric   else if (GV == GlobalRecord::Kind::Variable)
179b1c73532SDimitry Andric     Flags |= SymbolFlags::Data;
180b1c73532SDimitry Andric 
181b1c73532SDimitry Andric   Name = copyString(Name);
182b1c73532SDimitry Andric   auto Result = Globals.insert({Name, nullptr});
183b1c73532SDimitry Andric   if (Result.second)
184b1c73532SDimitry Andric     Result.first->second =
185ac9a064cSDimitry Andric         std::make_unique<GlobalRecord>(Name, Linkage, Flags, GV, Inlined);
18699aabd70SDimitry Andric   else {
187b1c73532SDimitry Andric     updateLinkage(Result.first->second.get(), Linkage);
18899aabd70SDimitry Andric     updateFlags(Result.first->second.get(), Flags);
18999aabd70SDimitry Andric   }
190b1c73532SDimitry Andric   return Result.first->second.get();
191b1c73532SDimitry Andric }
192b1c73532SDimitry Andric 
addObjCInterface(StringRef Name,RecordLinkage Linkage,ObjCIFSymbolKind SymType)193b1c73532SDimitry Andric ObjCInterfaceRecord *RecordsSlice::addObjCInterface(StringRef Name,
194b1c73532SDimitry Andric                                                     RecordLinkage Linkage,
195ac9a064cSDimitry Andric                                                     ObjCIFSymbolKind SymType) {
196b1c73532SDimitry Andric   Name = copyString(Name);
197b1c73532SDimitry Andric   auto Result = Classes.insert({Name, nullptr});
198ac9a064cSDimitry Andric   if (Result.second)
199b1c73532SDimitry Andric     Result.first->second =
200ac9a064cSDimitry Andric         std::make_unique<ObjCInterfaceRecord>(Name, Linkage, SymType);
201ac9a064cSDimitry Andric   else
202ac9a064cSDimitry Andric     Result.first->second->updateLinkageForSymbols(SymType, Linkage);
203b1c73532SDimitry Andric   return Result.first->second.get();
204b1c73532SDimitry Andric }
205ac9a064cSDimitry Andric 
mergeFlags(SymbolFlags Flags,RecordLinkage Linkage)20699aabd70SDimitry Andric SymbolFlags Record::mergeFlags(SymbolFlags Flags, RecordLinkage Linkage) {
20799aabd70SDimitry Andric   // Add Linkage properties into Flags.
20899aabd70SDimitry Andric   switch (Linkage) {
20999aabd70SDimitry Andric   case RecordLinkage::Rexported:
21099aabd70SDimitry Andric     Flags |= SymbolFlags::Rexported;
21199aabd70SDimitry Andric     return Flags;
21299aabd70SDimitry Andric   case RecordLinkage::Undefined:
21399aabd70SDimitry Andric     Flags |= SymbolFlags::Undefined;
21499aabd70SDimitry Andric     return Flags;
21599aabd70SDimitry Andric   default:
21699aabd70SDimitry Andric     return Flags;
21799aabd70SDimitry Andric   }
21899aabd70SDimitry Andric }
219b1c73532SDimitry Andric 
addObjCCategory(ObjCCategoryRecord * Record)220b1c73532SDimitry Andric bool ObjCInterfaceRecord::addObjCCategory(ObjCCategoryRecord *Record) {
221b1c73532SDimitry Andric   auto Result = Categories.insert({Name, Record});
222b1c73532SDimitry Andric   return Result.second;
223b1c73532SDimitry Andric }
224b1c73532SDimitry Andric 
addObjCCategory(StringRef ClassToExtend,StringRef Category)225b1c73532SDimitry Andric ObjCCategoryRecord *RecordsSlice::addObjCCategory(StringRef ClassToExtend,
226b1c73532SDimitry Andric                                                   StringRef Category) {
227b1c73532SDimitry Andric   Category = copyString(Category);
228ac9a064cSDimitry Andric   ClassToExtend = copyString(ClassToExtend);
229b1c73532SDimitry Andric 
230b1c73532SDimitry Andric   // Add owning record first into record slice.
231b1c73532SDimitry Andric   auto Result =
232b1c73532SDimitry Andric       Categories.insert({std::make_pair(ClassToExtend, Category), nullptr});
233b1c73532SDimitry Andric   if (Result.second)
234b1c73532SDimitry Andric     Result.first->second =
235b1c73532SDimitry Andric         std::make_unique<ObjCCategoryRecord>(ClassToExtend, Category);
236b1c73532SDimitry Andric 
237b1c73532SDimitry Andric   // Then add reference to it in in the class.
238b1c73532SDimitry Andric   if (auto *ObjCClass = findObjCInterface(ClassToExtend))
239b1c73532SDimitry Andric     ObjCClass->addObjCCategory(Result.first->second.get());
240b1c73532SDimitry Andric 
241b1c73532SDimitry Andric   return Result.first->second.get();
242b1c73532SDimitry Andric }
243b1c73532SDimitry Andric 
getObjCIVars() const24499aabd70SDimitry Andric std::vector<ObjCIVarRecord *> ObjCContainerRecord::getObjCIVars() const {
24599aabd70SDimitry Andric   std::vector<ObjCIVarRecord *> Records;
24699aabd70SDimitry Andric   llvm::for_each(IVars,
24799aabd70SDimitry Andric                  [&](auto &Record) { Records.push_back(Record.second.get()); });
24899aabd70SDimitry Andric   return Records;
24999aabd70SDimitry Andric }
25099aabd70SDimitry Andric 
25199aabd70SDimitry Andric std::vector<ObjCCategoryRecord *>
getObjCCategories() const25299aabd70SDimitry Andric ObjCInterfaceRecord::getObjCCategories() const {
25399aabd70SDimitry Andric   std::vector<ObjCCategoryRecord *> Records;
25499aabd70SDimitry Andric   llvm::for_each(Categories,
25599aabd70SDimitry Andric                  [&](auto &Record) { Records.push_back(Record.second); });
25699aabd70SDimitry Andric   return Records;
25799aabd70SDimitry Andric }
25899aabd70SDimitry Andric 
addObjCIVar(StringRef IVar,RecordLinkage Linkage)259b1c73532SDimitry Andric ObjCIVarRecord *ObjCContainerRecord::addObjCIVar(StringRef IVar,
260b1c73532SDimitry Andric                                                  RecordLinkage Linkage) {
261b1c73532SDimitry Andric   auto Result = IVars.insert({IVar, nullptr});
262b1c73532SDimitry Andric   if (Result.second)
26399aabd70SDimitry Andric     Result.first->second = std::make_unique<ObjCIVarRecord>(IVar, Linkage);
264b1c73532SDimitry Andric   return Result.first->second.get();
265b1c73532SDimitry Andric }
266b1c73532SDimitry Andric 
addObjCIVar(ObjCContainerRecord * Container,StringRef Name,RecordLinkage Linkage)267b1c73532SDimitry Andric ObjCIVarRecord *RecordsSlice::addObjCIVar(ObjCContainerRecord *Container,
268b1c73532SDimitry Andric                                           StringRef Name,
269b1c73532SDimitry Andric                                           RecordLinkage Linkage) {
270b1c73532SDimitry Andric   Name = copyString(Name);
271b1c73532SDimitry Andric   ObjCIVarRecord *Record = Container->addObjCIVar(Name, Linkage);
272b1c73532SDimitry Andric   updateLinkage(Record, Linkage);
273b1c73532SDimitry Andric   return Record;
274b1c73532SDimitry Andric }
275b1c73532SDimitry Andric 
copyString(StringRef String)276b1c73532SDimitry Andric StringRef RecordsSlice::copyString(StringRef String) {
277b1c73532SDimitry Andric   if (String.empty())
278b1c73532SDimitry Andric     return {};
279b1c73532SDimitry Andric 
280b1c73532SDimitry Andric   if (StringAllocator.identifyObject(String.data()))
281b1c73532SDimitry Andric     return String;
282b1c73532SDimitry Andric 
283b1c73532SDimitry Andric   void *Ptr = StringAllocator.Allocate(String.size(), 1);
284b1c73532SDimitry Andric   memcpy(Ptr, String.data(), String.size());
285b1c73532SDimitry Andric   return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
286b1c73532SDimitry Andric }
287b1c73532SDimitry Andric 
getBinaryAttrs()288b1c73532SDimitry Andric RecordsSlice::BinaryAttrs &RecordsSlice::getBinaryAttrs() {
289b1c73532SDimitry Andric   if (!hasBinaryAttrs())
290b1c73532SDimitry Andric     BA = std::make_unique<BinaryAttrs>();
291b1c73532SDimitry Andric   return *BA;
292b1c73532SDimitry Andric }
29399aabd70SDimitry Andric 
visit(RecordVisitor & V) const29499aabd70SDimitry Andric void RecordsSlice::visit(RecordVisitor &V) const {
29599aabd70SDimitry Andric   for (auto &G : Globals)
29699aabd70SDimitry Andric     V.visitGlobal(*G.second);
29799aabd70SDimitry Andric   for (auto &C : Classes)
29899aabd70SDimitry Andric     V.visitObjCInterface(*C.second);
29999aabd70SDimitry Andric   for (auto &Cat : Categories)
30099aabd70SDimitry Andric     V.visitObjCCategory(*Cat.second);
30199aabd70SDimitry Andric }
30299aabd70SDimitry Andric 
30399aabd70SDimitry Andric static std::unique_ptr<InterfaceFile>
createInterfaceFile(const Records & Slices,StringRef InstallName)30499aabd70SDimitry Andric createInterfaceFile(const Records &Slices, StringRef InstallName) {
30599aabd70SDimitry Andric   // Pickup symbols first.
30699aabd70SDimitry Andric   auto Symbols = std::make_unique<SymbolSet>();
30799aabd70SDimitry Andric   for (auto &S : Slices) {
30899aabd70SDimitry Andric     if (S->empty())
30999aabd70SDimitry Andric       continue;
31099aabd70SDimitry Andric     auto &BA = S->getBinaryAttrs();
31199aabd70SDimitry Andric     if (BA.InstallName != InstallName)
31299aabd70SDimitry Andric       continue;
31399aabd70SDimitry Andric 
31499aabd70SDimitry Andric     SymbolConverter Converter(Symbols.get(), S->getTarget(),
31599aabd70SDimitry Andric                               !BA.TwoLevelNamespace);
31699aabd70SDimitry Andric     S->visit(Converter);
31799aabd70SDimitry Andric   }
31899aabd70SDimitry Andric 
31999aabd70SDimitry Andric   auto File = std::make_unique<InterfaceFile>(std::move(Symbols));
32099aabd70SDimitry Andric   File->setInstallName(InstallName);
32199aabd70SDimitry Andric   // Assign other attributes.
32299aabd70SDimitry Andric   for (auto &S : Slices) {
32399aabd70SDimitry Andric     if (S->empty())
32499aabd70SDimitry Andric       continue;
32599aabd70SDimitry Andric     auto &BA = S->getBinaryAttrs();
32699aabd70SDimitry Andric     if (BA.InstallName != InstallName)
32799aabd70SDimitry Andric       continue;
32899aabd70SDimitry Andric     const Target &Targ = S->getTarget();
32999aabd70SDimitry Andric     File->addTarget(Targ);
330ac9a064cSDimitry Andric     File->setFromBinaryAttrs(BA, Targ);
33199aabd70SDimitry Andric   }
33299aabd70SDimitry Andric 
33399aabd70SDimitry Andric   return File;
33499aabd70SDimitry Andric }
33599aabd70SDimitry Andric 
33699aabd70SDimitry Andric std::unique_ptr<InterfaceFile>
convertToInterfaceFile(const Records & Slices)33799aabd70SDimitry Andric llvm::MachO::convertToInterfaceFile(const Records &Slices) {
33899aabd70SDimitry Andric   std::unique_ptr<InterfaceFile> File;
33999aabd70SDimitry Andric   if (Slices.empty())
34099aabd70SDimitry Andric     return File;
34199aabd70SDimitry Andric 
34299aabd70SDimitry Andric   SetVector<StringRef> InstallNames;
34399aabd70SDimitry Andric   for (auto &S : Slices) {
34499aabd70SDimitry Andric     auto Name = S->getBinaryAttrs().InstallName;
34599aabd70SDimitry Andric     if (Name.empty())
34699aabd70SDimitry Andric       continue;
34799aabd70SDimitry Andric     InstallNames.insert(Name);
34899aabd70SDimitry Andric   }
34999aabd70SDimitry Andric 
35099aabd70SDimitry Andric   File = createInterfaceFile(Slices, *InstallNames.begin());
3514df029ccSDimitry Andric   for (StringRef IN : llvm::drop_begin(InstallNames))
3524df029ccSDimitry Andric     File->addDocument(createInterfaceFile(Slices, IN));
35399aabd70SDimitry Andric 
35499aabd70SDimitry Andric   return File;
35599aabd70SDimitry Andric }
356