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