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