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