1351278Sdim//===- InterfaceFile.cpp --------------------------------------------------===//
2351278Sdim//
3351278Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4351278Sdim// See https://llvm.org/LICENSE.txt for license information.
5351278Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6351278Sdim//
7351278Sdim//===----------------------------------------------------------------------===//
8351278Sdim//
9351278Sdim// Implements the Interface File.
10351278Sdim//
11351278Sdim//===----------------------------------------------------------------------===//
12351278Sdim
13351278Sdim#include "llvm/TextAPI/MachO/InterfaceFile.h"
14351278Sdim#include <iomanip>
15351278Sdim#include <sstream>
16351278Sdim
17351278Sdimnamespace llvm {
18351278Sdimnamespace MachO {
19351278Sdimnamespace detail {
20351278Sdimtemplate <typename C>
21351278Sdimtypename C::iterator addEntry(C &Container, StringRef InstallName) {
22351278Sdim  auto I = partition_point(Container, [=](const InterfaceFileRef &O) {
23351278Sdim    return O.getInstallName() < InstallName;
24351278Sdim  });
25351278Sdim  if (I != Container.end() && I->getInstallName() == InstallName)
26351278Sdim    return I;
27351278Sdim
28351278Sdim  return Container.emplace(I, InstallName);
29351278Sdim}
30360784Sdim
31360784Sdimtemplate <typename C>
32360784Sdimtypename C::iterator addEntry(C &Container, const Target &Target_) {
33360784Sdim  auto Iter =
34360784Sdim      lower_bound(Container, Target_, [](const Target &LHS, const Target &RHS) {
35360784Sdim        return LHS < RHS;
36360784Sdim      });
37360784Sdim  if ((Iter != std::end(Container)) && !(Target_ < *Iter))
38360784Sdim    return Iter;
39360784Sdim
40360784Sdim  return Container.insert(Iter, Target_);
41360784Sdim}
42351278Sdim} // end namespace detail.
43351278Sdim
44360784Sdimvoid InterfaceFileRef::addTarget(const Target &Target) {
45360784Sdim  detail::addEntry(Targets, Target);
46351278Sdim}
47351278Sdim
48360784Sdimvoid InterfaceFile::addAllowableClient(StringRef InstallName,
49360784Sdim                                       const Target &Target) {
50360784Sdim  auto Client = detail::addEntry(AllowableClients, InstallName);
51360784Sdim  Client->addTarget(Target);
52360784Sdim}
53360784Sdim
54351278Sdimvoid InterfaceFile::addReexportedLibrary(StringRef InstallName,
55360784Sdim                                         const Target &Target) {
56351278Sdim  auto Lib = detail::addEntry(ReexportedLibraries, InstallName);
57360784Sdim  Lib->addTarget(Target);
58351278Sdim}
59351278Sdim
60360784Sdimvoid InterfaceFile::addParentUmbrella(const Target &Target_, StringRef Parent) {
61360784Sdim  auto Iter = lower_bound(ParentUmbrellas, Target_,
62360784Sdim                          [](const std::pair<Target, std::string> &LHS,
63360784Sdim                             Target RHS) { return LHS.first < RHS; });
64351278Sdim
65360784Sdim  if ((Iter != ParentUmbrellas.end()) && !(Target_ < Iter->first)) {
66360784Sdim    Iter->second = Parent;
67351278Sdim    return;
68351278Sdim  }
69351278Sdim
70360784Sdim  ParentUmbrellas.emplace(Iter, Target_, Parent);
71351278Sdim  return;
72351278Sdim}
73351278Sdim
74360784Sdimvoid InterfaceFile::addUUID(const Target &Target_, StringRef UUID) {
75360784Sdim  auto Iter = lower_bound(UUIDs, Target_,
76360784Sdim                          [](const std::pair<Target, std::string> &LHS,
77360784Sdim                             Target RHS) { return LHS.first < RHS; });
78360784Sdim
79360784Sdim  if ((Iter != UUIDs.end()) && !(Target_ < Iter->first)) {
80360784Sdim    Iter->second = UUID;
81360784Sdim    return;
82360784Sdim  }
83360784Sdim
84360784Sdim  UUIDs.emplace(Iter, Target_, UUID);
85360784Sdim  return;
86360784Sdim}
87360784Sdim
88360784Sdimvoid InterfaceFile::addUUID(const Target &Target, uint8_t UUID[16]) {
89351278Sdim  std::stringstream Stream;
90351278Sdim  for (unsigned i = 0; i < 16; ++i) {
91351278Sdim    if (i == 4 || i == 6 || i == 8 || i == 10)
92351278Sdim      Stream << '-';
93351278Sdim    Stream << std::setfill('0') << std::setw(2) << std::uppercase << std::hex
94351278Sdim           << static_cast<int>(UUID[i]);
95351278Sdim  }
96360784Sdim  addUUID(Target, Stream.str());
97351278Sdim}
98351278Sdim
99360784Sdimvoid InterfaceFile::addTarget(const Target &Target) {
100360784Sdim  detail::addEntry(Targets, Target);
101360784Sdim}
102360784Sdim
103360784SdimInterfaceFile::const_filtered_target_range
104360784SdimInterfaceFile::targets(ArchitectureSet Archs) const {
105360784Sdim  std::function<bool(const Target &)> fn = [Archs](const Target &Target_) {
106360784Sdim    return Archs.has(Target_.Arch);
107360784Sdim  };
108360784Sdim  return make_filter_range(Targets, fn);
109360784Sdim}
110360784Sdim
111351278Sdimvoid InterfaceFile::addSymbol(SymbolKind Kind, StringRef Name,
112360784Sdim                              const TargetList &Targets, SymbolFlags Flags) {
113351278Sdim  Name = copyString(Name);
114351278Sdim  auto result = Symbols.try_emplace(SymbolsMapKey{Kind, Name}, nullptr);
115351278Sdim  if (result.second)
116360784Sdim    result.first->second = new (Allocator) Symbol{Kind, Name, Targets, Flags};
117351278Sdim  else
118360784Sdim    for (const auto &Target : Targets)
119360784Sdim      result.first->second->addTarget(Target);
120351278Sdim}
121351278Sdim
122351278Sdim} // end namespace MachO.
123351278Sdim} // end namespace llvm.
124