InterfaceFile.cpp revision 360784
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/MachO/InterfaceFile.h"
14#include <iomanip>
15#include <sstream>
16
17namespace llvm {
18namespace MachO {
19namespace detail {
20template <typename C>
21typename C::iterator addEntry(C &Container, StringRef InstallName) {
22  auto I = partition_point(Container, [=](const InterfaceFileRef &O) {
23    return O.getInstallName() < InstallName;
24  });
25  if (I != Container.end() && I->getInstallName() == InstallName)
26    return I;
27
28  return Container.emplace(I, InstallName);
29}
30
31template <typename C>
32typename C::iterator addEntry(C &Container, const Target &Target_) {
33  auto Iter =
34      lower_bound(Container, Target_, [](const Target &LHS, const Target &RHS) {
35        return LHS < RHS;
36      });
37  if ((Iter != std::end(Container)) && !(Target_ < *Iter))
38    return Iter;
39
40  return Container.insert(Iter, Target_);
41}
42} // end namespace detail.
43
44void InterfaceFileRef::addTarget(const Target &Target) {
45  detail::addEntry(Targets, Target);
46}
47
48void InterfaceFile::addAllowableClient(StringRef InstallName,
49                                       const Target &Target) {
50  auto Client = detail::addEntry(AllowableClients, InstallName);
51  Client->addTarget(Target);
52}
53
54void InterfaceFile::addReexportedLibrary(StringRef InstallName,
55                                         const Target &Target) {
56  auto Lib = detail::addEntry(ReexportedLibraries, InstallName);
57  Lib->addTarget(Target);
58}
59
60void InterfaceFile::addParentUmbrella(const Target &Target_, StringRef Parent) {
61  auto Iter = lower_bound(ParentUmbrellas, Target_,
62                          [](const std::pair<Target, std::string> &LHS,
63                             Target RHS) { return LHS.first < RHS; });
64
65  if ((Iter != ParentUmbrellas.end()) && !(Target_ < Iter->first)) {
66    Iter->second = Parent;
67    return;
68  }
69
70  ParentUmbrellas.emplace(Iter, Target_, Parent);
71  return;
72}
73
74void 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 = UUID;
81    return;
82  }
83
84  UUIDs.emplace(Iter, Target_, UUID);
85  return;
86}
87
88void InterfaceFile::addUUID(const Target &Target, uint8_t UUID[16]) {
89  std::stringstream Stream;
90  for (unsigned i = 0; i < 16; ++i) {
91    if (i == 4 || i == 6 || i == 8 || i == 10)
92      Stream << '-';
93    Stream << std::setfill('0') << std::setw(2) << std::uppercase << std::hex
94           << static_cast<int>(UUID[i]);
95  }
96  addUUID(Target, Stream.str());
97}
98
99void InterfaceFile::addTarget(const Target &Target) {
100  detail::addEntry(Targets, Target);
101}
102
103InterfaceFile::const_filtered_target_range
104InterfaceFile::targets(ArchitectureSet Archs) const {
105  std::function<bool(const Target &)> fn = [Archs](const Target &Target_) {
106    return Archs.has(Target_.Arch);
107  };
108  return make_filter_range(Targets, fn);
109}
110
111void InterfaceFile::addSymbol(SymbolKind Kind, StringRef Name,
112                              const TargetList &Targets, SymbolFlags Flags) {
113  Name = copyString(Name);
114  auto result = Symbols.try_emplace(SymbolsMapKey{Kind, Name}, nullptr);
115  if (result.second)
116    result.first->second = new (Allocator) Symbol{Kind, Name, Targets, Flags};
117  else
118    for (const auto &Target : Targets)
119      result.first->second->addTarget(Target);
120}
121
122} // end namespace MachO.
123} // end namespace llvm.
124