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