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