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