1*0116d04dSCyndy Ishida //===- InterfaceFile.cpp --------------------------------------------------===//
2*0116d04dSCyndy Ishida //
3*0116d04dSCyndy Ishida // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0116d04dSCyndy Ishida // See https://llvm.org/LICENSE.txt for license information.
5*0116d04dSCyndy Ishida // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0116d04dSCyndy Ishida //
7*0116d04dSCyndy Ishida //===----------------------------------------------------------------------===//
8*0116d04dSCyndy Ishida //
9*0116d04dSCyndy Ishida // Implements the Interface File.
10*0116d04dSCyndy Ishida //
11*0116d04dSCyndy Ishida //===----------------------------------------------------------------------===//
12*0116d04dSCyndy Ishida 
13*0116d04dSCyndy Ishida #include "llvm/TextAPI/InterfaceFile.h"
14*0116d04dSCyndy Ishida #include <iomanip>
15*0116d04dSCyndy Ishida #include <sstream>
16*0116d04dSCyndy Ishida 
17*0116d04dSCyndy Ishida using namespace llvm;
18*0116d04dSCyndy Ishida using namespace llvm::MachO;
19*0116d04dSCyndy Ishida 
20*0116d04dSCyndy Ishida namespace {
21*0116d04dSCyndy Ishida template <typename C>
addEntry(C & Container,StringRef InstallName)22*0116d04dSCyndy Ishida typename C::iterator addEntry(C &Container, StringRef InstallName) {
23*0116d04dSCyndy Ishida   auto I = partition_point(Container, [=](const InterfaceFileRef &O) {
24*0116d04dSCyndy Ishida     return O.getInstallName() < InstallName;
25*0116d04dSCyndy Ishida   });
26*0116d04dSCyndy Ishida   if (I != Container.end() && I->getInstallName() == InstallName)
27*0116d04dSCyndy Ishida     return I;
28*0116d04dSCyndy Ishida 
29*0116d04dSCyndy Ishida   return Container.emplace(I, InstallName);
30*0116d04dSCyndy Ishida }
31*0116d04dSCyndy Ishida 
32*0116d04dSCyndy Ishida template <typename C>
addEntry(C & Container,const Target & Target_)33*0116d04dSCyndy Ishida typename C::iterator addEntry(C &Container, const Target &Target_) {
34*0116d04dSCyndy Ishida   auto Iter =
35*0116d04dSCyndy Ishida       lower_bound(Container, Target_, [](const Target &LHS, const Target &RHS) {
36*0116d04dSCyndy Ishida         return LHS < RHS;
37*0116d04dSCyndy Ishida       });
38*0116d04dSCyndy Ishida   if ((Iter != std::end(Container)) && !(Target_ < *Iter))
39*0116d04dSCyndy Ishida     return Iter;
40*0116d04dSCyndy Ishida 
41*0116d04dSCyndy Ishida   return Container.insert(Iter, Target_);
42*0116d04dSCyndy Ishida }
43*0116d04dSCyndy Ishida } // end namespace
44*0116d04dSCyndy Ishida 
addTarget(const Target & Target)45*0116d04dSCyndy Ishida void InterfaceFileRef::addTarget(const Target &Target) {
46*0116d04dSCyndy Ishida   addEntry(Targets, Target);
47*0116d04dSCyndy Ishida }
48*0116d04dSCyndy Ishida 
addAllowableClient(StringRef InstallName,const Target & Target)49*0116d04dSCyndy Ishida void InterfaceFile::addAllowableClient(StringRef InstallName,
50*0116d04dSCyndy Ishida                                        const Target &Target) {
51*0116d04dSCyndy Ishida   auto Client = addEntry(AllowableClients, InstallName);
52*0116d04dSCyndy Ishida   Client->addTarget(Target);
53*0116d04dSCyndy Ishida }
54*0116d04dSCyndy Ishida 
addReexportedLibrary(StringRef InstallName,const Target & Target)55*0116d04dSCyndy Ishida void InterfaceFile::addReexportedLibrary(StringRef InstallName,
56*0116d04dSCyndy Ishida                                          const Target &Target) {
57*0116d04dSCyndy Ishida   auto Lib = addEntry(ReexportedLibraries, InstallName);
58*0116d04dSCyndy Ishida   Lib->addTarget(Target);
59*0116d04dSCyndy Ishida }
60*0116d04dSCyndy Ishida 
addParentUmbrella(const Target & Target_,StringRef Parent)61*0116d04dSCyndy Ishida void InterfaceFile::addParentUmbrella(const Target &Target_, StringRef Parent) {
62*0116d04dSCyndy Ishida   auto Iter = lower_bound(ParentUmbrellas, Target_,
63*0116d04dSCyndy Ishida                           [](const std::pair<Target, std::string> &LHS,
64*0116d04dSCyndy Ishida                              Target RHS) { return LHS.first < RHS; });
65*0116d04dSCyndy Ishida 
66*0116d04dSCyndy Ishida   if ((Iter != ParentUmbrellas.end()) && !(Target_ < Iter->first)) {
67*0116d04dSCyndy Ishida     Iter->second = std::string(Parent);
68*0116d04dSCyndy Ishida     return;
69*0116d04dSCyndy Ishida   }
70*0116d04dSCyndy Ishida 
71*0116d04dSCyndy Ishida   ParentUmbrellas.emplace(Iter, Target_, std::string(Parent));
72*0116d04dSCyndy Ishida }
73*0116d04dSCyndy Ishida 
addUUID(const Target & Target_,StringRef UUID)74*0116d04dSCyndy Ishida void InterfaceFile::addUUID(const Target &Target_, StringRef UUID) {
75*0116d04dSCyndy Ishida   auto Iter = lower_bound(UUIDs, Target_,
76*0116d04dSCyndy Ishida                           [](const std::pair<Target, std::string> &LHS,
77*0116d04dSCyndy Ishida                              Target RHS) { return LHS.first < RHS; });
78*0116d04dSCyndy Ishida 
79*0116d04dSCyndy Ishida   if ((Iter != UUIDs.end()) && !(Target_ < Iter->first)) {
80*0116d04dSCyndy Ishida     Iter->second = std::string(UUID);
81*0116d04dSCyndy Ishida     return;
82*0116d04dSCyndy Ishida   }
83*0116d04dSCyndy Ishida 
84*0116d04dSCyndy Ishida   UUIDs.emplace(Iter, Target_, std::string(UUID));
85*0116d04dSCyndy Ishida }
86*0116d04dSCyndy Ishida 
addUUID(const Target & Target,uint8_t UUID[16])87*0116d04dSCyndy Ishida void InterfaceFile::addUUID(const Target &Target, uint8_t UUID[16]) {
88*0116d04dSCyndy Ishida   std::stringstream Stream;
89*0116d04dSCyndy Ishida   for (unsigned i = 0; i < 16; ++i) {
90*0116d04dSCyndy Ishida     if (i == 4 || i == 6 || i == 8 || i == 10)
91*0116d04dSCyndy Ishida       Stream << '-';
92*0116d04dSCyndy Ishida     Stream << std::setfill('0') << std::setw(2) << std::uppercase << std::hex
93*0116d04dSCyndy Ishida            << static_cast<int>(UUID[i]);
94*0116d04dSCyndy Ishida   }
95*0116d04dSCyndy Ishida   addUUID(Target, Stream.str());
96*0116d04dSCyndy Ishida }
97*0116d04dSCyndy Ishida 
addTarget(const Target & Target)98*0116d04dSCyndy Ishida void InterfaceFile::addTarget(const Target &Target) {
99*0116d04dSCyndy Ishida   addEntry(Targets, Target);
100*0116d04dSCyndy Ishida }
101*0116d04dSCyndy Ishida 
102*0116d04dSCyndy Ishida InterfaceFile::const_filtered_target_range
targets(ArchitectureSet Archs) const103*0116d04dSCyndy Ishida InterfaceFile::targets(ArchitectureSet Archs) const {
104*0116d04dSCyndy Ishida   std::function<bool(const Target &)> fn = [Archs](const Target &Target_) {
105*0116d04dSCyndy Ishida     return Archs.has(Target_.Arch);
106*0116d04dSCyndy Ishida   };
107*0116d04dSCyndy Ishida   return make_filter_range(Targets, fn);
108*0116d04dSCyndy Ishida }
109*0116d04dSCyndy Ishida 
addSymbol(SymbolKind Kind,StringRef Name,const TargetList & Targets,SymbolFlags Flags)110*0116d04dSCyndy Ishida void InterfaceFile::addSymbol(SymbolKind Kind, StringRef Name,
111*0116d04dSCyndy Ishida                               const TargetList &Targets, SymbolFlags Flags) {
112*0116d04dSCyndy Ishida   Name = copyString(Name);
113*0116d04dSCyndy Ishida   auto result = Symbols.try_emplace(SymbolsMapKey{Kind, Name}, nullptr);
114*0116d04dSCyndy Ishida   if (result.second)
115*0116d04dSCyndy Ishida     result.first->second = new (Allocator) Symbol{Kind, Name, Targets, Flags};
116*0116d04dSCyndy Ishida   else
117*0116d04dSCyndy Ishida     for (const auto &Target : Targets)
118*0116d04dSCyndy Ishida       result.first->second->addTarget(Target);
119*0116d04dSCyndy Ishida }
120*0116d04dSCyndy Ishida 
addDocument(std::shared_ptr<InterfaceFile> && Document)121*0116d04dSCyndy Ishida void InterfaceFile::addDocument(std::shared_ptr<InterfaceFile> &&Document) {
122*0116d04dSCyndy Ishida   auto Pos = llvm::lower_bound(Documents, Document,
123*0116d04dSCyndy Ishida                                [](const std::shared_ptr<InterfaceFile> &LHS,
124*0116d04dSCyndy Ishida                                   const std::shared_ptr<InterfaceFile> &RHS) {
125*0116d04dSCyndy Ishida                                  return LHS->InstallName < RHS->InstallName;
126*0116d04dSCyndy Ishida                                });
127*0116d04dSCyndy Ishida   Document->Parent = this;
128*0116d04dSCyndy Ishida   Documents.insert(Pos, Document);
129*0116d04dSCyndy Ishida }
130*0116d04dSCyndy Ishida 
operator ==(const InterfaceFile & O) const131*0116d04dSCyndy Ishida bool InterfaceFile::operator==(const InterfaceFile &O) const {
132*0116d04dSCyndy Ishida   if (Targets != O.Targets)
133*0116d04dSCyndy Ishida     return false;
134*0116d04dSCyndy Ishida   if (InstallName != O.InstallName)
135*0116d04dSCyndy Ishida     return false;
136*0116d04dSCyndy Ishida   if ((CurrentVersion != O.CurrentVersion) ||
137*0116d04dSCyndy Ishida       (CompatibilityVersion != O.CompatibilityVersion))
138*0116d04dSCyndy Ishida     return false;
139*0116d04dSCyndy Ishida   if (SwiftABIVersion != O.SwiftABIVersion)
140*0116d04dSCyndy Ishida     return false;
141*0116d04dSCyndy Ishida   if (IsTwoLevelNamespace != O.IsTwoLevelNamespace)
142*0116d04dSCyndy Ishida     return false;
143*0116d04dSCyndy Ishida   if (IsAppExtensionSafe != O.IsAppExtensionSafe)
144*0116d04dSCyndy Ishida     return false;
145*0116d04dSCyndy Ishida   if (IsInstallAPI != O.IsInstallAPI)
146*0116d04dSCyndy Ishida     return false;
147*0116d04dSCyndy Ishida   if (ParentUmbrellas != O.ParentUmbrellas)
148*0116d04dSCyndy Ishida     return false;
149*0116d04dSCyndy Ishida   if (AllowableClients != O.AllowableClients)
150*0116d04dSCyndy Ishida     return false;
151*0116d04dSCyndy Ishida   if (ReexportedLibraries != O.ReexportedLibraries)
152*0116d04dSCyndy Ishida     return false;
153*0116d04dSCyndy Ishida   if (Symbols != O.Symbols)
154*0116d04dSCyndy Ishida     return false;
155*0116d04dSCyndy Ishida   if (!std::equal(Documents.begin(), Documents.end(), O.Documents.begin(),
156*0116d04dSCyndy Ishida                   O.Documents.end(),
157*0116d04dSCyndy Ishida                   [](const std::shared_ptr<InterfaceFile> LHS,
158*0116d04dSCyndy Ishida                      const std::shared_ptr<InterfaceFile> RHS) {
159*0116d04dSCyndy Ishida                     return *LHS == *RHS;
160*0116d04dSCyndy Ishida                   }))
161*0116d04dSCyndy Ishida     return false;
162*0116d04dSCyndy Ishida   return true;
163*0116d04dSCyndy Ishida }
164