Home | History | Annotate | Line # | Download | only in TextAPI
      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