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