InterfaceFile.h revision 360784
1//===- llvm/TextAPI/MachO/IntefaceFile.h - TAPI Interface File --*- C++ -*-===// 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// A generic and abstract interface representation for linkable objects. This 10// could be an MachO executable, bundle, dylib, or text-based stub file. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef LLVM_TEXTAPI_MACHO_INTERFACE_FILE_H 15#define LLVM_TEXTAPI_MACHO_INTERFACE_FILE_H 16 17#include "llvm/ADT/BitmaskEnum.h" 18#include "llvm/ADT/DenseMap.h" 19#include "llvm/ADT/Hashing.h" 20#include "llvm/ADT/StringRef.h" 21#include "llvm/ADT/iterator.h" 22#include "llvm/BinaryFormat/MachO.h" 23#include "llvm/BinaryFormat/Magic.h" 24#include "llvm/Support/Allocator.h" 25#include "llvm/Support/Error.h" 26#include "llvm/TextAPI/MachO/Architecture.h" 27#include "llvm/TextAPI/MachO/ArchitectureSet.h" 28#include "llvm/TextAPI/MachO/PackedVersion.h" 29#include "llvm/TextAPI/MachO/Platform.h" 30#include "llvm/TextAPI/MachO/Symbol.h" 31#include "llvm/TextAPI/MachO/Target.h" 32 33namespace llvm { 34namespace MachO { 35 36/// Defines a list of Objective-C constraints. 37enum class ObjCConstraintType : unsigned { 38 /// No constraint. 39 None = 0, 40 41 /// Retain/Release. 42 Retain_Release = 1, 43 44 /// Retain/Release for Simulator. 45 Retain_Release_For_Simulator = 2, 46 47 /// Retain/Release or Garbage Collection. 48 Retain_Release_Or_GC = 3, 49 50 /// Garbage Collection. 51 GC = 4, 52}; 53 54// clang-format off 55 56/// Defines the file type this file represents. 57enum FileType : unsigned { 58 /// Invalid file type. 59 Invalid = 0U, 60 61 /// Text-based stub file (.tbd) version 1.0 62 TBD_V1 = 1U << 0, 63 64 /// Text-based stub file (.tbd) version 2.0 65 TBD_V2 = 1U << 1, 66 67 /// Text-based stub file (.tbd) version 3.0 68 TBD_V3 = 1U << 2, 69 70 /// Text-based stub file (.tbd) version 4.0 71 TBD_V4 = 1U << 3, 72 73 All = ~0U, 74 75 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/All), 76}; 77 78// clang-format on 79 80/// Reference to an interface file. 81class InterfaceFileRef { 82public: 83 InterfaceFileRef() = default; 84 85 InterfaceFileRef(StringRef InstallName) : InstallName(InstallName) {} 86 87 InterfaceFileRef(StringRef InstallName, const TargetList Targets) 88 : InstallName(InstallName), Targets(std::move(Targets)) {} 89 90 StringRef getInstallName() const { return InstallName; }; 91 92 void addTarget(const Target &Target); 93 template <typename RangeT> void addTargets(RangeT &&Targets) { 94 for (const auto &Target : Targets) 95 addTarget(Target(Target)); 96 } 97 98 using const_target_iterator = TargetList::const_iterator; 99 using const_target_range = llvm::iterator_range<const_target_iterator>; 100 const_target_range targets() const { return {Targets}; } 101 102 ArchitectureSet getArchitectures() const { 103 return mapToArchitectureSet(Targets); 104 } 105 106 PlatformSet getPlatforms() const { return mapToPlatformSet(Targets); } 107 108 bool operator==(const InterfaceFileRef &O) const { 109 return std::tie(InstallName, Targets) == std::tie(O.InstallName, O.Targets); 110 } 111 112 bool operator!=(const InterfaceFileRef &O) const { 113 return std::tie(InstallName, Targets) != std::tie(O.InstallName, O.Targets); 114 } 115 116 bool operator<(const InterfaceFileRef &O) const { 117 return std::tie(InstallName, Targets) < std::tie(O.InstallName, O.Targets); 118 } 119 120private: 121 std::string InstallName; 122 TargetList Targets; 123}; 124 125} // end namespace MachO. 126 127struct SymbolsMapKey { 128 MachO::SymbolKind Kind; 129 StringRef Name; 130 131 SymbolsMapKey(MachO::SymbolKind Kind, StringRef Name) 132 : Kind(Kind), Name(Name) {} 133}; 134template <> struct DenseMapInfo<SymbolsMapKey> { 135 static inline SymbolsMapKey getEmptyKey() { 136 return SymbolsMapKey(MachO::SymbolKind::GlobalSymbol, StringRef{}); 137 } 138 139 static inline SymbolsMapKey getTombstoneKey() { 140 return SymbolsMapKey(MachO::SymbolKind::ObjectiveCInstanceVariable, 141 StringRef{}); 142 } 143 144 static unsigned getHashValue(const SymbolsMapKey &Key) { 145 return hash_combine(hash_value(Key.Kind), hash_value(Key.Name)); 146 } 147 148 static bool isEqual(const SymbolsMapKey &LHS, const SymbolsMapKey &RHS) { 149 return std::tie(LHS.Kind, LHS.Name) == std::tie(RHS.Kind, RHS.Name); 150 } 151}; 152 153namespace MachO { 154 155/// Defines the interface file. 156class InterfaceFile { 157public: 158 /// Set the path from which this file was generated (if applicable). 159 /// 160 /// \param Path_ The path to the source file. 161 void setPath(StringRef Path_) { Path = Path_; } 162 163 /// Get the path from which this file was generated (if applicable). 164 /// 165 /// \return The path to the source file or empty. 166 StringRef getPath() const { return Path; } 167 168 /// Set the file type. 169 /// 170 /// This is used by the YAML writer to identify the specification it should 171 /// use for writing the file. 172 /// 173 /// \param Kind The file type. 174 void setFileType(FileType Kind) { FileKind = Kind; } 175 176 /// Get the file type. 177 /// 178 /// \return The file type. 179 FileType getFileType() const { return FileKind; } 180 181 /// Get the architectures. 182 /// 183 /// \return The applicable architectures. 184 ArchitectureSet getArchitectures() const { 185 return mapToArchitectureSet(Targets); 186 } 187 188 /// Get the platforms. 189 /// 190 /// \return The applicable platforms. 191 PlatformSet getPlatforms() const { return mapToPlatformSet(Targets); } 192 193 /// Set and add target. 194 /// 195 /// \param Target the target to add into. 196 void addTarget(const Target &Target); 197 198 /// Set and add targets. 199 /// 200 /// Add the subset of llvm::triples that is supported by Tapi 201 /// 202 /// \param Targets the collection of targets. 203 template <typename RangeT> void addTargets(RangeT &&Targets) { 204 for (const auto &Target_ : Targets) 205 addTarget(Target(Target_)); 206 } 207 208 using const_target_iterator = TargetList::const_iterator; 209 using const_target_range = llvm::iterator_range<const_target_iterator>; 210 const_target_range targets() const { return {Targets}; } 211 212 using const_filtered_target_iterator = 213 llvm::filter_iterator<const_target_iterator, 214 std::function<bool(const Target &)>>; 215 using const_filtered_target_range = 216 llvm::iterator_range<const_filtered_target_iterator>; 217 const_filtered_target_range targets(ArchitectureSet Archs) const; 218 219 /// Set the install name of the library. 220 void setInstallName(StringRef InstallName_) { InstallName = InstallName_; } 221 222 /// Get the install name of the library. 223 StringRef getInstallName() const { return InstallName; } 224 225 /// Set the current version of the library. 226 void setCurrentVersion(PackedVersion Version) { CurrentVersion = Version; } 227 228 /// Get the current version of the library. 229 PackedVersion getCurrentVersion() const { return CurrentVersion; } 230 231 /// Set the compatibility version of the library. 232 void setCompatibilityVersion(PackedVersion Version) { 233 CompatibilityVersion = Version; 234 } 235 236 /// Get the compatibility version of the library. 237 PackedVersion getCompatibilityVersion() const { return CompatibilityVersion; } 238 239 /// Set the Swift ABI version of the library. 240 void setSwiftABIVersion(uint8_t Version) { SwiftABIVersion = Version; } 241 242 /// Get the Swift ABI version of the library. 243 uint8_t getSwiftABIVersion() const { return SwiftABIVersion; } 244 245 /// Specify if the library uses two-level namespace (or flat namespace). 246 void setTwoLevelNamespace(bool V = true) { IsTwoLevelNamespace = V; } 247 248 /// Check if the library uses two-level namespace. 249 bool isTwoLevelNamespace() const { return IsTwoLevelNamespace; } 250 251 /// Specify if the library is application extension safe (or not). 252 void setApplicationExtensionSafe(bool V = true) { IsAppExtensionSafe = V; } 253 254 /// Check if the library is application extension safe. 255 bool isApplicationExtensionSafe() const { return IsAppExtensionSafe; } 256 257 /// Set the Objective-C constraint. 258 void setObjCConstraint(ObjCConstraintType Constraint) { 259 ObjcConstraint = Constraint; 260 } 261 262 /// Get the Objective-C constraint. 263 ObjCConstraintType getObjCConstraint() const { return ObjcConstraint; } 264 265 /// Specify if this file was generated during InstallAPI (or not). 266 void setInstallAPI(bool V = true) { IsInstallAPI = V; } 267 268 /// Check if this file was generated during InstallAPI. 269 bool isInstallAPI() const { return IsInstallAPI; } 270 271 /// Set the parent umbrella frameworks. 272 /// \param Target_ The target applicable to Parent 273 /// \param Parent The name of Parent 274 void addParentUmbrella(const Target &Target_, StringRef Parent); 275 const std::vector<std::pair<Target, std::string>> &umbrellas() const { 276 return ParentUmbrellas; 277 } 278 279 /// Get the parent umbrella framework. 280 const std::vector<std::pair<Target, std::string>> getParentUmbrellas() const { 281 return ParentUmbrellas; 282 } 283 284 /// Add an allowable client. 285 /// 286 /// Mach-O Dynamic libraries have the concept of allowable clients that are 287 /// checked during static link time. The name of the application or library 288 /// that is being generated needs to match one of the allowable clients or the 289 /// linker refuses to link this library. 290 /// 291 /// \param InstallName The name of the client that is allowed to link this library. 292 /// \param Target The target triple for which this applies. 293 void addAllowableClient(StringRef InstallName, const Target &Target); 294 295 /// Get the list of allowable clients. 296 /// 297 /// \return Returns a list of allowable clients. 298 const std::vector<InterfaceFileRef> &allowableClients() const { 299 return AllowableClients; 300 } 301 302 /// Add a re-exported library. 303 /// 304 /// \param InstallName The name of the library to re-export. 305 /// \param Target The target triple for which this applies. 306 void addReexportedLibrary(StringRef InstallName, const Target &Target); 307 308 /// Get the list of re-exported libraries. 309 /// 310 /// \return Returns a list of re-exported libraries. 311 const std::vector<InterfaceFileRef> &reexportedLibraries() const { 312 return ReexportedLibraries; 313 } 314 315 /// Add an Target/UUID pair. 316 /// 317 /// \param Target The target triple for which this applies. 318 /// \param UUID The UUID of the library for the specified architecture. 319 void addUUID(const Target &Target, StringRef UUID); 320 321 /// Add an Target/UUID pair. 322 /// 323 /// \param Target The target triple for which this applies. 324 /// \param UUID The UUID of the library for the specified architecture. 325 void addUUID(const Target &Target, uint8_t UUID[16]); 326 327 /// Get the list of Target/UUID pairs. 328 /// 329 /// \return Returns a list of Target/UUID pairs. 330 const std::vector<std::pair<Target, std::string>> &uuids() const { 331 return UUIDs; 332 } 333 334 /// Add a symbol to the symbols list or extend an existing one. 335 void addSymbol(SymbolKind Kind, StringRef Name, const TargetList &Targets, 336 SymbolFlags Flags = SymbolFlags::None); 337 338 using SymbolMapType = DenseMap<SymbolsMapKey, Symbol *>; 339 struct const_symbol_iterator 340 : public iterator_adaptor_base< 341 const_symbol_iterator, SymbolMapType::const_iterator, 342 std::forward_iterator_tag, const Symbol *, ptrdiff_t, 343 const Symbol *, const Symbol *> { 344 const_symbol_iterator() = default; 345 346 template <typename U> 347 const_symbol_iterator(U &&u) 348 : iterator_adaptor_base(std::forward<U &&>(u)) {} 349 350 reference operator*() const { return I->second; } 351 pointer operator->() const { return I->second; } 352 }; 353 354 using const_symbol_range = iterator_range<const_symbol_iterator>; 355 356 using const_filtered_symbol_iterator = 357 filter_iterator<const_symbol_iterator, 358 std::function<bool(const Symbol *)>>; 359 using const_filtered_symbol_range = 360 iterator_range<const_filtered_symbol_iterator>; 361 362 const_symbol_range symbols() const { 363 return {Symbols.begin(), Symbols.end()}; 364 } 365 366 const_filtered_symbol_range exports() const { 367 std::function<bool(const Symbol *)> fn = [](const Symbol *Symbol) { 368 return !Symbol->isUndefined(); 369 }; 370 return make_filter_range( 371 make_range<const_symbol_iterator>({Symbols.begin()}, {Symbols.end()}), 372 fn); 373 } 374 375 const_filtered_symbol_range undefineds() const { 376 std::function<bool(const Symbol *)> fn = [](const Symbol *Symbol) { 377 return Symbol->isUndefined(); 378 }; 379 return make_filter_range( 380 make_range<const_symbol_iterator>({Symbols.begin()}, {Symbols.end()}), 381 fn); 382 } 383 384private: 385 llvm::BumpPtrAllocator Allocator; 386 StringRef copyString(StringRef String) { 387 if (String.empty()) 388 return {}; 389 390 void *Ptr = Allocator.Allocate(String.size(), 1); 391 memcpy(Ptr, String.data(), String.size()); 392 return StringRef(reinterpret_cast<const char *>(Ptr), String.size()); 393 } 394 395 TargetList Targets; 396 std::string Path; 397 FileType FileKind; 398 std::string InstallName; 399 PackedVersion CurrentVersion; 400 PackedVersion CompatibilityVersion; 401 uint8_t SwiftABIVersion{0}; 402 bool IsTwoLevelNamespace{false}; 403 bool IsAppExtensionSafe{false}; 404 bool IsInstallAPI{false}; 405 ObjCConstraintType ObjcConstraint = ObjCConstraintType::None; 406 std::vector<std::pair<Target, std::string>> ParentUmbrellas; 407 std::vector<InterfaceFileRef> AllowableClients; 408 std::vector<InterfaceFileRef> ReexportedLibraries; 409 std::vector<std::pair<Target, std::string>> UUIDs; 410 SymbolMapType Symbols; 411}; 412 413} // end namespace MachO. 414} // end namespace llvm. 415 416#endif // LLVM_TEXTAPI_MACHO_INTERFACE_FILE_H 417