OffloadBinary.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===--- Offloading.h - Utilities for handling offloading code -*- 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. // This file contains the binary format used for budingling device metadata with
  15. // an associated device image. The data can then be stored inside a host object
  16. // file to create a fat binary and read by the linker. This is intended to be a
  17. // thin wrapper around the image itself. If this format becomes sufficiently
  18. // complex it should be moved to a standard binary format like msgpack or ELF.
  19. //
  20. //===----------------------------------------------------------------------===//
  21. #ifndef LLVM_OBJECT_OFFLOADBINARY_H
  22. #define LLVM_OBJECT_OFFLOADBINARY_H
  23. #include "llvm/ADT/StringMap.h"
  24. #include "llvm/ADT/StringRef.h"
  25. #include "llvm/Object/Binary.h"
  26. #include "llvm/Support/Error.h"
  27. #include "llvm/Support/MemoryBuffer.h"
  28. #include <memory>
  29. namespace llvm {
  30. namespace object {
  31. /// The producer of the associated offloading image.
  32. enum OffloadKind : uint16_t {
  33. OFK_None = 0,
  34. OFK_OpenMP,
  35. OFK_Cuda,
  36. OFK_HIP,
  37. OFK_LAST,
  38. };
  39. /// The type of contents the offloading image contains.
  40. enum ImageKind : uint16_t {
  41. IMG_None = 0,
  42. IMG_Object,
  43. IMG_Bitcode,
  44. IMG_Cubin,
  45. IMG_Fatbinary,
  46. IMG_PTX,
  47. IMG_LAST,
  48. };
  49. /// A simple binary serialization of an offloading file. We use this format to
  50. /// embed the offloading image into the host executable so it can be extracted
  51. /// and used by the linker.
  52. ///
  53. /// Many of these could be stored in the same section by the time the linker
  54. /// sees it so we mark this information with a header. The version is used to
  55. /// detect ABI stability and the size is used to find other offloading entries
  56. /// that may exist in the same section. All offsets are given as absolute byte
  57. /// offsets from the beginning of the file.
  58. class OffloadBinary : public Binary {
  59. public:
  60. using string_iterator = StringMap<StringRef>::const_iterator;
  61. using string_iterator_range = iterator_range<string_iterator>;
  62. /// The current version of the binary used for backwards compatibility.
  63. static const uint32_t Version = 1;
  64. /// The offloading metadata that will be serialized to a memory buffer.
  65. struct OffloadingImage {
  66. ImageKind TheImageKind;
  67. OffloadKind TheOffloadKind;
  68. uint32_t Flags;
  69. StringMap<StringRef> StringData;
  70. std::unique_ptr<MemoryBuffer> Image;
  71. };
  72. /// Attempt to parse the offloading binary stored in \p Data.
  73. static Expected<std::unique_ptr<OffloadBinary>> create(MemoryBufferRef);
  74. /// Serialize the contents of \p File to a binary buffer to be read later.
  75. static std::unique_ptr<MemoryBuffer> write(const OffloadingImage &);
  76. static uint64_t getAlignment() { return 8; }
  77. ImageKind getImageKind() const { return TheEntry->TheImageKind; }
  78. OffloadKind getOffloadKind() const { return TheEntry->TheOffloadKind; }
  79. uint32_t getVersion() const { return TheHeader->Version; }
  80. uint32_t getFlags() const { return TheEntry->Flags; }
  81. uint64_t getSize() const { return TheHeader->Size; }
  82. StringRef getTriple() const { return getString("triple"); }
  83. StringRef getArch() const { return getString("arch"); }
  84. StringRef getImage() const {
  85. return StringRef(&Buffer[TheEntry->ImageOffset], TheEntry->ImageSize);
  86. }
  87. // Iterator over all the key and value pairs in the binary.
  88. string_iterator_range strings() const {
  89. return string_iterator_range(StringData.begin(), StringData.end());
  90. }
  91. StringRef getString(StringRef Key) const { return StringData.lookup(Key); }
  92. static bool classof(const Binary *V) { return V->isOffloadFile(); }
  93. struct Header {
  94. uint8_t Magic[4] = {0x10, 0xFF, 0x10, 0xAD}; // 0x10FF10AD magic bytes.
  95. uint32_t Version = OffloadBinary::Version; // Version identifier.
  96. uint64_t Size; // Size in bytes of this entire binary.
  97. uint64_t EntryOffset; // Offset of the metadata entry in bytes.
  98. uint64_t EntrySize; // Size of the metadata entry in bytes.
  99. };
  100. struct Entry {
  101. ImageKind TheImageKind; // The kind of the image stored.
  102. OffloadKind TheOffloadKind; // The producer of this image.
  103. uint32_t Flags; // Additional flags associated with the image.
  104. uint64_t StringOffset; // Offset in bytes to the string map.
  105. uint64_t NumStrings; // Number of entries in the string map.
  106. uint64_t ImageOffset; // Offset in bytes of the actual binary image.
  107. uint64_t ImageSize; // Size in bytes of the binary image.
  108. };
  109. struct StringEntry {
  110. uint64_t KeyOffset;
  111. uint64_t ValueOffset;
  112. };
  113. private:
  114. OffloadBinary(MemoryBufferRef Source, const Header *TheHeader,
  115. const Entry *TheEntry)
  116. : Binary(Binary::ID_Offload, Source), Buffer(Source.getBufferStart()),
  117. TheHeader(TheHeader), TheEntry(TheEntry) {
  118. const StringEntry *StringMapBegin =
  119. reinterpret_cast<const StringEntry *>(&Buffer[TheEntry->StringOffset]);
  120. for (uint64_t I = 0, E = TheEntry->NumStrings; I != E; ++I) {
  121. StringRef Key = &Buffer[StringMapBegin[I].KeyOffset];
  122. StringData[Key] = &Buffer[StringMapBegin[I].ValueOffset];
  123. }
  124. }
  125. OffloadBinary(const OffloadBinary &Other) = delete;
  126. /// Map from keys to offsets in the binary.
  127. StringMap<StringRef> StringData;
  128. /// Raw pointer to the MemoryBufferRef for convenience.
  129. const char *Buffer;
  130. /// Location of the header within the binary.
  131. const Header *TheHeader;
  132. /// Location of the metadata entries within the binary.
  133. const Entry *TheEntry;
  134. };
  135. /// A class to contain the binary information for a single OffloadBinary that
  136. /// owns its memory.
  137. class OffloadFile : public OwningBinary<OffloadBinary> {
  138. public:
  139. using TargetID = std::pair<StringRef, StringRef>;
  140. OffloadFile(std::unique_ptr<OffloadBinary> Binary,
  141. std::unique_ptr<MemoryBuffer> Buffer)
  142. : OwningBinary<OffloadBinary>(std::move(Binary), std::move(Buffer)) {}
  143. /// We use the Triple and Architecture pair to group linker inputs together.
  144. /// This conversion function lets us use these inputs in a hash-map.
  145. operator TargetID() const {
  146. return std::make_pair(getBinary()->getTriple(), getBinary()->getArch());
  147. }
  148. };
  149. /// Extracts embedded device offloading code from a memory \p Buffer to a list
  150. /// of \p Binaries.
  151. Error extractOffloadBinaries(MemoryBufferRef Buffer,
  152. SmallVectorImpl<OffloadFile> &Binaries);
  153. /// Convert a string \p Name to an image kind.
  154. ImageKind getImageKind(StringRef Name);
  155. /// Convert an image kind to its string representation.
  156. StringRef getImageKindName(ImageKind Name);
  157. /// Convert a string \p Name to an offload kind.
  158. OffloadKind getOffloadKind(StringRef Name);
  159. /// Convert an offload kind to its string representation.
  160. StringRef getOffloadKindName(OffloadKind Name);
  161. } // namespace object
  162. } // namespace llvm
  163. #endif
  164. #ifdef __GNUC__
  165. #pragma GCC diagnostic pop
  166. #endif