InterfaceFile.h 15 KB

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