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::addTarget(const Target &Target) {
63   addEntry(Targets, Target);
64 }
65 
66 InterfaceFile::const_filtered_target_range
67 InterfaceFile::targets(ArchitectureSet Archs) const {
68   std::function<bool(const Target &)> fn = [Archs](const Target &Target_) {
69     return Archs.has(Target_.Arch);
70   };
71   return make_filter_range(Targets, fn);
72 }
73 
74 void InterfaceFile::addDocument(std::shared_ptr<InterfaceFile> &&Document) {
75   auto Pos = llvm::lower_bound(Documents, Document,
76                                [](const std::shared_ptr<InterfaceFile> &LHS,
77                                   const std::shared_ptr<InterfaceFile> &RHS) {
78                                  return LHS->InstallName < RHS->InstallName;
79                                });
80   Document->Parent = this;
81   Documents.insert(Pos, Document);
82 }
83 
84 static bool isYAMLTextStub(const FileType &Kind) {
85   return (Kind >= FileType::TBD_V1) && (Kind < FileType::TBD_V5);
86 }
87 
88 bool InterfaceFile::operator==(const InterfaceFile &O) const {
89   if (Targets != O.Targets)
90     return false;
91   if (InstallName != O.InstallName)
92     return false;
93   if ((CurrentVersion != O.CurrentVersion) ||
94       (CompatibilityVersion != O.CompatibilityVersion))
95     return false;
96   if (SwiftABIVersion != O.SwiftABIVersion)
97     return false;
98   if (IsTwoLevelNamespace != O.IsTwoLevelNamespace)
99     return false;
100   if (IsAppExtensionSafe != O.IsAppExtensionSafe)
101     return false;
102   if (ParentUmbrellas != O.ParentUmbrellas)
103     return false;
104   if (AllowableClients != O.AllowableClients)
105     return false;
106   if (ReexportedLibraries != O.ReexportedLibraries)
107     return false;
108   if (*SymbolsSet != *O.SymbolsSet)
109     return false;
110   // Don't compare run search paths for older filetypes that cannot express
111   // them.
112   if (!(isYAMLTextStub(FileKind)) && !(isYAMLTextStub(O.FileKind))) {
113     if (RPaths != O.RPaths)
114       return false;
115     if (mapToPlatformVersionSet(Targets) != mapToPlatformVersionSet(O.Targets))
116       return false;
117   }
118 
119   if (!std::equal(Documents.begin(), Documents.end(), O.Documents.begin(),
120                   O.Documents.end(),
121                   [](const std::shared_ptr<InterfaceFile> LHS,
122                      const std::shared_ptr<InterfaceFile> RHS) {
123                     return *LHS == *RHS;
124                   }))
125     return false;
126   return true;
127 }
128