xref: /llvm-project/llvm/lib/TextAPI/RecordsSlice.cpp (revision d2f0d991943a9bbf2452adcb11e9a12d5843952b)
1b04b8975SCyndy Ishida //===- RecordsSlice.cpp --------------------------------------------------===//
2b04b8975SCyndy Ishida //
3b04b8975SCyndy Ishida // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b04b8975SCyndy Ishida // See https://llvm.org/LICENSE.txt for license information.
5b04b8975SCyndy Ishida // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b04b8975SCyndy Ishida //
7b04b8975SCyndy Ishida //===----------------------------------------------------------------------===//
8b04b8975SCyndy Ishida //
9b04b8975SCyndy Ishida // Implements the Records Slice APIs.
10b04b8975SCyndy Ishida //
11b04b8975SCyndy Ishida //===----------------------------------------------------------------------===//
12b04b8975SCyndy Ishida 
13b04b8975SCyndy Ishida #include "llvm/TextAPI/RecordsSlice.h"
145ea15fabSCyndy Ishida #include "llvm/ADT/SetVector.h"
153a080a01SCyndy Ishida #include "llvm/TextAPI/InterfaceFile.h"
16b04b8975SCyndy Ishida #include "llvm/TextAPI/Record.h"
17b04b8975SCyndy Ishida #include "llvm/TextAPI/Symbol.h"
18b04b8975SCyndy Ishida #include <utility>
19b04b8975SCyndy Ishida 
20b04b8975SCyndy Ishida using namespace llvm;
21b04b8975SCyndy Ishida using namespace llvm::MachO;
22b04b8975SCyndy Ishida 
23b04b8975SCyndy Ishida Record *RecordsSlice::addRecord(StringRef Name, SymbolFlags Flags,
24b04b8975SCyndy Ishida                                 GlobalRecord::Kind GV, RecordLinkage Linkage) {
25b04b8975SCyndy Ishida   // Find a specific Record type to capture.
264460fa88SCyndy Ishida   auto [APIName, SymKind, InterfaceType] = parseSymbol(Name);
27b04b8975SCyndy Ishida   Name = APIName;
28b04b8975SCyndy Ishida   switch (SymKind) {
29d9a9872eSCyndy Ishida   case EncodeKind::GlobalSymbol:
30b04b8975SCyndy Ishida     return addGlobal(Name, Linkage, GV, Flags);
31d9a9872eSCyndy Ishida   case EncodeKind::ObjectiveCClass:
324460fa88SCyndy Ishida     return addObjCInterface(Name, Linkage, InterfaceType);
334460fa88SCyndy Ishida   case EncodeKind::ObjectiveCClassEHType: {
344460fa88SCyndy Ishida     ObjCInterfaceRecord *Rec = addObjCInterface(Name, Linkage, InterfaceType);
354460fa88SCyndy Ishida     // When classes without ehtype are used in try/catch blocks
364460fa88SCyndy Ishida     // a weak-defined symbol is exported.
374460fa88SCyndy Ishida     if ((Flags & SymbolFlags::WeakDefined) == SymbolFlags::WeakDefined)
384460fa88SCyndy Ishida       updateFlags(Rec, SymbolFlags::WeakDefined);
394460fa88SCyndy Ishida     return Rec;
404460fa88SCyndy Ishida   }
41d9a9872eSCyndy Ishida   case EncodeKind::ObjectiveCInstanceVariable: {
42b04b8975SCyndy Ishida     auto [Super, IVar] = Name.split('.');
43b04b8975SCyndy Ishida     // Attempt to find super class.
44b04b8975SCyndy Ishida     ObjCContainerRecord *Container = findContainer(/*isIVar=*/false, Super);
45b04b8975SCyndy Ishida     // If not found, create extension since there is no mapped class symbol.
46b04b8975SCyndy Ishida     if (Container == nullptr)
47b04b8975SCyndy Ishida       Container = addObjCCategory(Super, {});
48b04b8975SCyndy Ishida     return addObjCIVar(Container, IVar, Linkage);
49b04b8975SCyndy Ishida   }
50b04b8975SCyndy Ishida   }
51b04b8975SCyndy Ishida 
52b04b8975SCyndy Ishida   llvm_unreachable("unexpected symbol kind when adding to Record Slice");
53b04b8975SCyndy Ishida }
54b04b8975SCyndy Ishida 
55b04b8975SCyndy Ishida ObjCContainerRecord *RecordsSlice::findContainer(bool IsIVar,
56b04b8975SCyndy Ishida                                                  StringRef Name) const {
57b04b8975SCyndy Ishida   StringRef Super = IsIVar ? Name.split('.').first : Name;
58b04b8975SCyndy Ishida   ObjCContainerRecord *Container = findObjCInterface(Super);
59b04b8975SCyndy Ishida   // Ivars can only exist with extensions, if they did not come from
60b04b8975SCyndy Ishida   // class.
61b04b8975SCyndy Ishida   if (Container == nullptr)
62b04b8975SCyndy Ishida     Container = findObjCCategory(Super, "");
63b04b8975SCyndy Ishida   return Container;
64b04b8975SCyndy Ishida }
65b04b8975SCyndy Ishida 
66b04b8975SCyndy Ishida template <typename R, typename C = RecordMap<R>, typename K = StringRef>
67b04b8975SCyndy Ishida R *findRecord(K Key, const C &Container) {
68b04b8975SCyndy Ishida   const auto *Record = Container.find(Key);
69b04b8975SCyndy Ishida   if (Record == Container.end())
70b04b8975SCyndy Ishida     return nullptr;
71b04b8975SCyndy Ishida   return Record->second.get();
72b04b8975SCyndy Ishida }
73b04b8975SCyndy Ishida 
74b04b8975SCyndy Ishida GlobalRecord *RecordsSlice::findGlobal(StringRef Name,
75b04b8975SCyndy Ishida                                        GlobalRecord::Kind GV) const {
76b04b8975SCyndy Ishida   auto *Record = findRecord<GlobalRecord>(Name, Globals);
77b04b8975SCyndy Ishida   if (!Record)
78b04b8975SCyndy Ishida     return nullptr;
79b04b8975SCyndy Ishida 
80b04b8975SCyndy Ishida   switch (GV) {
81b04b8975SCyndy Ishida   case GlobalRecord::Kind::Variable: {
82b04b8975SCyndy Ishida     if (!Record->isVariable())
83b04b8975SCyndy Ishida       return nullptr;
84b04b8975SCyndy Ishida     break;
85b04b8975SCyndy Ishida   }
86b04b8975SCyndy Ishida   case GlobalRecord::Kind::Function: {
87b04b8975SCyndy Ishida     if (!Record->isFunction())
88b04b8975SCyndy Ishida       return nullptr;
89b04b8975SCyndy Ishida     break;
90b04b8975SCyndy Ishida   }
91b04b8975SCyndy Ishida   case GlobalRecord::Kind::Unknown:
92b04b8975SCyndy Ishida     return Record;
93b04b8975SCyndy Ishida   }
94b04b8975SCyndy Ishida 
95b04b8975SCyndy Ishida   return Record;
96b04b8975SCyndy Ishida }
97b04b8975SCyndy Ishida 
984460fa88SCyndy Ishida RecordLinkage
994460fa88SCyndy Ishida ObjCInterfaceRecord::getLinkageForSymbol(ObjCIFSymbolKind CurrType) const {
1004460fa88SCyndy Ishida   assert(CurrType <= ObjCIFSymbolKind::EHType &&
1014460fa88SCyndy Ishida          "expected single ObjCIFSymbolKind enum value");
1024460fa88SCyndy Ishida   if (CurrType == ObjCIFSymbolKind::Class)
1034460fa88SCyndy Ishida     return Linkages.Class;
1044460fa88SCyndy Ishida 
1054460fa88SCyndy Ishida   if (CurrType == ObjCIFSymbolKind::MetaClass)
1064460fa88SCyndy Ishida     return Linkages.MetaClass;
1074460fa88SCyndy Ishida 
1084460fa88SCyndy Ishida   if (CurrType == ObjCIFSymbolKind::EHType)
1094460fa88SCyndy Ishida     return Linkages.EHType;
1104460fa88SCyndy Ishida 
1114460fa88SCyndy Ishida   llvm_unreachable("unexpected ObjCIFSymbolKind");
1124460fa88SCyndy Ishida }
1134460fa88SCyndy Ishida 
1144460fa88SCyndy Ishida void ObjCInterfaceRecord::updateLinkageForSymbols(ObjCIFSymbolKind SymType,
1154460fa88SCyndy Ishida                                                   RecordLinkage Link) {
1164460fa88SCyndy Ishida   if ((SymType & ObjCIFSymbolKind::Class) == ObjCIFSymbolKind::Class)
1174460fa88SCyndy Ishida     Linkages.Class = std::max(Link, Linkages.Class);
1184460fa88SCyndy Ishida   if ((SymType & ObjCIFSymbolKind::MetaClass) == ObjCIFSymbolKind::MetaClass)
1194460fa88SCyndy Ishida     Linkages.MetaClass = std::max(Link, Linkages.MetaClass);
1204460fa88SCyndy Ishida   if ((SymType & ObjCIFSymbolKind::EHType) == ObjCIFSymbolKind::EHType)
1214460fa88SCyndy Ishida     Linkages.EHType = std::max(Link, Linkages.EHType);
1224460fa88SCyndy Ishida 
1234460fa88SCyndy Ishida   // Obj-C Classes represent multiple symbols that could have competing
1244460fa88SCyndy Ishida   // linkages, in this case assign the largest one, when querying the linkage of
1254460fa88SCyndy Ishida   // the record itself. This allows visitors pick whether they want to account
1264460fa88SCyndy Ishida   // for complete symbol information.
1274460fa88SCyndy Ishida   Linkage =
1284460fa88SCyndy Ishida       std::max(Linkages.Class, std::max(Linkages.MetaClass, Linkages.EHType));
1294460fa88SCyndy Ishida }
1304460fa88SCyndy Ishida 
131b04b8975SCyndy Ishida ObjCInterfaceRecord *RecordsSlice::findObjCInterface(StringRef Name) const {
132b04b8975SCyndy Ishida   return findRecord<ObjCInterfaceRecord>(Name, Classes);
133b04b8975SCyndy Ishida }
134b04b8975SCyndy Ishida 
135b04b8975SCyndy Ishida ObjCCategoryRecord *RecordsSlice::findObjCCategory(StringRef ClassToExtend,
136b04b8975SCyndy Ishida                                                    StringRef Category) const {
137b04b8975SCyndy Ishida   return findRecord<ObjCCategoryRecord>(std::make_pair(ClassToExtend, Category),
138b04b8975SCyndy Ishida                                         Categories);
139b04b8975SCyndy Ishida }
140b04b8975SCyndy Ishida 
141b04b8975SCyndy Ishida ObjCIVarRecord *ObjCContainerRecord::findObjCIVar(StringRef IVar) const {
142b04b8975SCyndy Ishida   return findRecord<ObjCIVarRecord>(IVar, IVars);
143b04b8975SCyndy Ishida }
144b04b8975SCyndy Ishida 
145b04b8975SCyndy Ishida ObjCIVarRecord *RecordsSlice::findObjCIVar(bool IsScopedName,
146b04b8975SCyndy Ishida                                            StringRef Name) const {
147b04b8975SCyndy Ishida   // If scoped name, the name of the container is known.
148b04b8975SCyndy Ishida   if (IsScopedName) {
149b04b8975SCyndy Ishida     // IVar does not exist if there is not a container assigned to it.
150b04b8975SCyndy Ishida     auto *Container = findContainer(/*IsIVar=*/true, Name);
151b04b8975SCyndy Ishida     if (!Container)
152b04b8975SCyndy Ishida       return nullptr;
153b04b8975SCyndy Ishida 
154b04b8975SCyndy Ishida     StringRef IVar = Name.substr(Name.find_first_of('.') + 1);
155b04b8975SCyndy Ishida     return Container->findObjCIVar(IVar);
156b04b8975SCyndy Ishida   }
157b04b8975SCyndy Ishida 
158b04b8975SCyndy Ishida   // Otherwise traverse through containers and attempt to find IVar.
159b04b8975SCyndy Ishida   auto getIVar = [Name](auto &Records) -> ObjCIVarRecord * {
160b04b8975SCyndy Ishida     for (const auto &[_, Container] : Records) {
161b04b8975SCyndy Ishida       if (auto *IVarR = Container->findObjCIVar(Name))
162b04b8975SCyndy Ishida         return IVarR;
163b04b8975SCyndy Ishida     }
164b04b8975SCyndy Ishida     return nullptr;
165b04b8975SCyndy Ishida   };
166b04b8975SCyndy Ishida 
167b04b8975SCyndy Ishida   if (auto *IVarRecord = getIVar(Classes))
168b04b8975SCyndy Ishida     return IVarRecord;
169b04b8975SCyndy Ishida 
170b04b8975SCyndy Ishida   return getIVar(Categories);
171b04b8975SCyndy Ishida }
172b04b8975SCyndy Ishida 
173b04b8975SCyndy Ishida GlobalRecord *RecordsSlice::addGlobal(StringRef Name, RecordLinkage Linkage,
17450ae8a2aSCyndy Ishida                                       GlobalRecord::Kind GV, SymbolFlags Flags,
17550ae8a2aSCyndy Ishida                                       bool Inlined) {
176b04b8975SCyndy Ishida   if (GV == GlobalRecord::Kind::Function)
177b04b8975SCyndy Ishida     Flags |= SymbolFlags::Text;
178b04b8975SCyndy Ishida   else if (GV == GlobalRecord::Kind::Variable)
179b04b8975SCyndy Ishida     Flags |= SymbolFlags::Data;
180b04b8975SCyndy Ishida 
181b04b8975SCyndy Ishida   Name = copyString(Name);
182b04b8975SCyndy Ishida   auto Result = Globals.insert({Name, nullptr});
183b04b8975SCyndy Ishida   if (Result.second)
184b04b8975SCyndy Ishida     Result.first->second =
18550ae8a2aSCyndy Ishida         std::make_unique<GlobalRecord>(Name, Linkage, Flags, GV, Inlined);
1865ea15fabSCyndy Ishida   else {
187b04b8975SCyndy Ishida     updateLinkage(Result.first->second.get(), Linkage);
1885ea15fabSCyndy Ishida     updateFlags(Result.first->second.get(), Flags);
1895ea15fabSCyndy Ishida   }
190b04b8975SCyndy Ishida   return Result.first->second.get();
191b04b8975SCyndy Ishida }
192b04b8975SCyndy Ishida 
193b04b8975SCyndy Ishida ObjCInterfaceRecord *RecordsSlice::addObjCInterface(StringRef Name,
194b04b8975SCyndy Ishida                                                     RecordLinkage Linkage,
1954460fa88SCyndy Ishida                                                     ObjCIFSymbolKind SymType) {
196b04b8975SCyndy Ishida   Name = copyString(Name);
197b04b8975SCyndy Ishida   auto Result = Classes.insert({Name, nullptr});
1984460fa88SCyndy Ishida   if (Result.second)
199b04b8975SCyndy Ishida     Result.first->second =
2004460fa88SCyndy Ishida         std::make_unique<ObjCInterfaceRecord>(Name, Linkage, SymType);
2014460fa88SCyndy Ishida   else
2024460fa88SCyndy Ishida     Result.first->second->updateLinkageForSymbols(SymType, Linkage);
203b04b8975SCyndy Ishida   return Result.first->second.get();
204b04b8975SCyndy Ishida }
2054460fa88SCyndy Ishida 
2065ea15fabSCyndy Ishida SymbolFlags Record::mergeFlags(SymbolFlags Flags, RecordLinkage Linkage) {
2075ea15fabSCyndy Ishida   // Add Linkage properties into Flags.
2085ea15fabSCyndy Ishida   switch (Linkage) {
2095ea15fabSCyndy Ishida   case RecordLinkage::Rexported:
2105ea15fabSCyndy Ishida     Flags |= SymbolFlags::Rexported;
2115ea15fabSCyndy Ishida     return Flags;
2125ea15fabSCyndy Ishida   case RecordLinkage::Undefined:
2135ea15fabSCyndy Ishida     Flags |= SymbolFlags::Undefined;
2145ea15fabSCyndy Ishida     return Flags;
2155ea15fabSCyndy Ishida   default:
2165ea15fabSCyndy Ishida     return Flags;
2175ea15fabSCyndy Ishida   }
2185ea15fabSCyndy Ishida }
219b04b8975SCyndy Ishida 
220b04b8975SCyndy Ishida bool ObjCInterfaceRecord::addObjCCategory(ObjCCategoryRecord *Record) {
221b04b8975SCyndy Ishida   auto Result = Categories.insert({Name, Record});
222b04b8975SCyndy Ishida   return Result.second;
223b04b8975SCyndy Ishida }
224b04b8975SCyndy Ishida 
225b04b8975SCyndy Ishida ObjCCategoryRecord *RecordsSlice::addObjCCategory(StringRef ClassToExtend,
226b04b8975SCyndy Ishida                                                   StringRef Category) {
227b04b8975SCyndy Ishida   Category = copyString(Category);
22810ccde30SCyndy Ishida   ClassToExtend = copyString(ClassToExtend);
229b04b8975SCyndy Ishida 
230b04b8975SCyndy Ishida   // Add owning record first into record slice.
231b04b8975SCyndy Ishida   auto Result =
232b04b8975SCyndy Ishida       Categories.insert({std::make_pair(ClassToExtend, Category), nullptr});
233b04b8975SCyndy Ishida   if (Result.second)
234b04b8975SCyndy Ishida     Result.first->second =
235b04b8975SCyndy Ishida         std::make_unique<ObjCCategoryRecord>(ClassToExtend, Category);
236b04b8975SCyndy Ishida 
237b04b8975SCyndy Ishida   // Then add reference to it in in the class.
238b04b8975SCyndy Ishida   if (auto *ObjCClass = findObjCInterface(ClassToExtend))
239b04b8975SCyndy Ishida     ObjCClass->addObjCCategory(Result.first->second.get());
240b04b8975SCyndy Ishida 
241b04b8975SCyndy Ishida   return Result.first->second.get();
242b04b8975SCyndy Ishida }
243b04b8975SCyndy Ishida 
2445ea15fabSCyndy Ishida std::vector<ObjCIVarRecord *> ObjCContainerRecord::getObjCIVars() const {
2455ea15fabSCyndy Ishida   std::vector<ObjCIVarRecord *> Records;
246*d2f0d991SKazu Hirata   Records.reserve(IVars.size());
247*d2f0d991SKazu Hirata   for (const auto &Record : IVars)
248*d2f0d991SKazu Hirata     Records.push_back(Record.second.get());
2495ea15fabSCyndy Ishida   return Records;
2505ea15fabSCyndy Ishida }
2515ea15fabSCyndy Ishida 
2525ea15fabSCyndy Ishida std::vector<ObjCCategoryRecord *>
2535ea15fabSCyndy Ishida ObjCInterfaceRecord::getObjCCategories() const {
2545ea15fabSCyndy Ishida   std::vector<ObjCCategoryRecord *> Records;
255*d2f0d991SKazu Hirata   Records.reserve(Categories.size());
256*d2f0d991SKazu Hirata   for (const auto &Record : Categories)
257*d2f0d991SKazu Hirata     Records.push_back(Record.second);
2585ea15fabSCyndy Ishida   return Records;
2595ea15fabSCyndy Ishida }
2605ea15fabSCyndy Ishida 
261b04b8975SCyndy Ishida ObjCIVarRecord *ObjCContainerRecord::addObjCIVar(StringRef IVar,
262b04b8975SCyndy Ishida                                                  RecordLinkage Linkage) {
263b04b8975SCyndy Ishida   auto Result = IVars.insert({IVar, nullptr});
264b04b8975SCyndy Ishida   if (Result.second)
2655ea15fabSCyndy Ishida     Result.first->second = std::make_unique<ObjCIVarRecord>(IVar, Linkage);
266b04b8975SCyndy Ishida   return Result.first->second.get();
267b04b8975SCyndy Ishida }
268b04b8975SCyndy Ishida 
269b04b8975SCyndy Ishida ObjCIVarRecord *RecordsSlice::addObjCIVar(ObjCContainerRecord *Container,
270b04b8975SCyndy Ishida                                           StringRef Name,
271b04b8975SCyndy Ishida                                           RecordLinkage Linkage) {
272b04b8975SCyndy Ishida   Name = copyString(Name);
273b04b8975SCyndy Ishida   ObjCIVarRecord *Record = Container->addObjCIVar(Name, Linkage);
274b04b8975SCyndy Ishida   updateLinkage(Record, Linkage);
275b04b8975SCyndy Ishida   return Record;
276b04b8975SCyndy Ishida }
277b04b8975SCyndy Ishida 
278b04b8975SCyndy Ishida StringRef RecordsSlice::copyString(StringRef String) {
279b04b8975SCyndy Ishida   if (String.empty())
280b04b8975SCyndy Ishida     return {};
281b04b8975SCyndy Ishida 
282b04b8975SCyndy Ishida   if (StringAllocator.identifyObject(String.data()))
283b04b8975SCyndy Ishida     return String;
284b04b8975SCyndy Ishida 
285b04b8975SCyndy Ishida   void *Ptr = StringAllocator.Allocate(String.size(), 1);
286b04b8975SCyndy Ishida   memcpy(Ptr, String.data(), String.size());
287b04b8975SCyndy Ishida   return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
288b04b8975SCyndy Ishida }
289b04b8975SCyndy Ishida 
290b04b8975SCyndy Ishida RecordsSlice::BinaryAttrs &RecordsSlice::getBinaryAttrs() {
291b04b8975SCyndy Ishida   if (!hasBinaryAttrs())
292b04b8975SCyndy Ishida     BA = std::make_unique<BinaryAttrs>();
293b04b8975SCyndy Ishida   return *BA;
294b04b8975SCyndy Ishida }
2955ea15fabSCyndy Ishida 
2965ea15fabSCyndy Ishida void RecordsSlice::visit(RecordVisitor &V) const {
2975ea15fabSCyndy Ishida   for (auto &G : Globals)
2985ea15fabSCyndy Ishida     V.visitGlobal(*G.second);
2995ea15fabSCyndy Ishida   for (auto &C : Classes)
3005ea15fabSCyndy Ishida     V.visitObjCInterface(*C.second);
3015ea15fabSCyndy Ishida   for (auto &Cat : Categories)
3025ea15fabSCyndy Ishida     V.visitObjCCategory(*Cat.second);
3035ea15fabSCyndy Ishida }
3045ea15fabSCyndy Ishida 
3055ea15fabSCyndy Ishida static std::unique_ptr<InterfaceFile>
3065ea15fabSCyndy Ishida createInterfaceFile(const Records &Slices, StringRef InstallName) {
3075ea15fabSCyndy Ishida   // Pickup symbols first.
3085ea15fabSCyndy Ishida   auto Symbols = std::make_unique<SymbolSet>();
3095ea15fabSCyndy Ishida   for (auto &S : Slices) {
3105ea15fabSCyndy Ishida     if (S->empty())
3115ea15fabSCyndy Ishida       continue;
3125ea15fabSCyndy Ishida     auto &BA = S->getBinaryAttrs();
3135ea15fabSCyndy Ishida     if (BA.InstallName != InstallName)
3145ea15fabSCyndy Ishida       continue;
3155ea15fabSCyndy Ishida 
3165ea15fabSCyndy Ishida     SymbolConverter Converter(Symbols.get(), S->getTarget(),
3175ea15fabSCyndy Ishida                               !BA.TwoLevelNamespace);
3185ea15fabSCyndy Ishida     S->visit(Converter);
3195ea15fabSCyndy Ishida   }
3205ea15fabSCyndy Ishida 
3215ea15fabSCyndy Ishida   auto File = std::make_unique<InterfaceFile>(std::move(Symbols));
3225ea15fabSCyndy Ishida   File->setInstallName(InstallName);
3235ea15fabSCyndy Ishida   // Assign other attributes.
3245ea15fabSCyndy Ishida   for (auto &S : Slices) {
3255ea15fabSCyndy Ishida     if (S->empty())
3265ea15fabSCyndy Ishida       continue;
3275ea15fabSCyndy Ishida     auto &BA = S->getBinaryAttrs();
3285ea15fabSCyndy Ishida     if (BA.InstallName != InstallName)
3295ea15fabSCyndy Ishida       continue;
3305ea15fabSCyndy Ishida     const Target &Targ = S->getTarget();
3315ea15fabSCyndy Ishida     File->addTarget(Targ);
3323a080a01SCyndy Ishida     File->setFromBinaryAttrs(BA, Targ);
3335ea15fabSCyndy Ishida   }
3345ea15fabSCyndy Ishida 
3355ea15fabSCyndy Ishida   return File;
3365ea15fabSCyndy Ishida }
3375ea15fabSCyndy Ishida 
3385ea15fabSCyndy Ishida std::unique_ptr<InterfaceFile>
3395ea15fabSCyndy Ishida llvm::MachO::convertToInterfaceFile(const Records &Slices) {
3405ea15fabSCyndy Ishida   std::unique_ptr<InterfaceFile> File;
3415ea15fabSCyndy Ishida   if (Slices.empty())
3425ea15fabSCyndy Ishida     return File;
3435ea15fabSCyndy Ishida 
3445ea15fabSCyndy Ishida   SetVector<StringRef> InstallNames;
3455ea15fabSCyndy Ishida   for (auto &S : Slices) {
3465ea15fabSCyndy Ishida     auto Name = S->getBinaryAttrs().InstallName;
3475ea15fabSCyndy Ishida     if (Name.empty())
3485ea15fabSCyndy Ishida       continue;
3495ea15fabSCyndy Ishida     InstallNames.insert(Name);
3505ea15fabSCyndy Ishida   }
3515ea15fabSCyndy Ishida 
3525ea15fabSCyndy Ishida   File = createInterfaceFile(Slices, *InstallNames.begin());
35396f14ea6SKazu Hirata   for (StringRef IN : llvm::drop_begin(InstallNames))
35496f14ea6SKazu Hirata     File->addDocument(createInterfaceFile(Slices, IN));
3555ea15fabSCyndy Ishida 
3565ea15fabSCyndy Ishida   return File;
3575ea15fabSCyndy Ishida }
358