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