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::addUUID(const Target &Target_, StringRef UUID) { 63 auto Iter = lower_bound(UUIDs, Target_, 64 [](const std::pair<Target, std::string> &LHS, 65 Target RHS) { return LHS.first < RHS; }); 66 67 if ((Iter != UUIDs.end()) && !(Target_ < Iter->first)) { 68 Iter->second = std::string(UUID); 69 return; 70 } 71 72 UUIDs.emplace(Iter, Target_, std::string(UUID)); 73 } 74 75 void InterfaceFile::addUUID(const Target &Target, uint8_t UUID[16]) { 76 std::stringstream Stream; 77 for (unsigned i = 0; i < 16; ++i) { 78 if (i == 4 || i == 6 || i == 8 || i == 10) 79 Stream << '-'; 80 Stream << std::setfill('0') << std::setw(2) << std::uppercase << std::hex 81 << static_cast<int>(UUID[i]); 82 } 83 addUUID(Target, Stream.str()); 84 } 85 86 void InterfaceFile::addTarget(const Target &Target) { 87 addEntry(Targets, Target); 88 } 89 90 InterfaceFile::const_filtered_target_range 91 InterfaceFile::targets(ArchitectureSet Archs) const { 92 std::function<bool(const Target &)> fn = [Archs](const Target &Target_) { 93 return Archs.has(Target_.Arch); 94 }; 95 return make_filter_range(Targets, fn); 96 } 97 98 void InterfaceFile::addDocument(std::shared_ptr<InterfaceFile> &&Document) { 99 auto Pos = llvm::lower_bound(Documents, Document, 100 [](const std::shared_ptr<InterfaceFile> &LHS, 101 const std::shared_ptr<InterfaceFile> &RHS) { 102 return LHS->InstallName < RHS->InstallName; 103 }); 104 Document->Parent = this; 105 Documents.insert(Pos, Document); 106 } 107 108 static bool isYAMLTextStub(const FileType &Kind) { 109 return (Kind >= FileType::TBD_V1) && (Kind < FileType::TBD_V5); 110 } 111 112 bool InterfaceFile::operator==(const InterfaceFile &O) const { 113 if (Targets != O.Targets) 114 return false; 115 if (InstallName != O.InstallName) 116 return false; 117 if ((CurrentVersion != O.CurrentVersion) || 118 (CompatibilityVersion != O.CompatibilityVersion)) 119 return false; 120 if (SwiftABIVersion != O.SwiftABIVersion) 121 return false; 122 if (IsTwoLevelNamespace != O.IsTwoLevelNamespace) 123 return false; 124 if (IsAppExtensionSafe != O.IsAppExtensionSafe) 125 return false; 126 if (IsInstallAPI != O.IsInstallAPI) 127 return false; 128 if (ParentUmbrellas != O.ParentUmbrellas) 129 return false; 130 if (AllowableClients != O.AllowableClients) 131 return false; 132 if (ReexportedLibraries != O.ReexportedLibraries) 133 return false; 134 if (*SymbolsSet != *O.SymbolsSet) 135 return false; 136 // Don't compare run search paths for older filetypes that cannot express 137 // them. 138 if (!(isYAMLTextStub(FileKind)) && !(isYAMLTextStub(O.FileKind))) { 139 if (RPaths != O.RPaths) 140 return false; 141 if (mapToPlatformVersionSet(Targets) != mapToPlatformVersionSet(O.Targets)) 142 return false; 143 } 144 145 if (!std::equal(Documents.begin(), Documents.end(), O.Documents.begin(), 146 O.Documents.end(), 147 [](const std::shared_ptr<InterfaceFile> LHS, 148 const std::shared_ptr<InterfaceFile> RHS) { 149 return *LHS == *RHS; 150 })) 151 return false; 152 return true; 153 } 154