File indexing completed on 2026-05-10 08:44:20
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef LLVM_OBJECT_OFFLOADBINARY_H
0018 #define LLVM_OBJECT_OFFLOADBINARY_H
0019
0020 #include "llvm/ADT/MapVector.h"
0021 #include "llvm/ADT/SmallString.h"
0022 #include "llvm/ADT/StringRef.h"
0023 #include "llvm/Object/Binary.h"
0024 #include "llvm/Support/Error.h"
0025 #include "llvm/Support/MemoryBuffer.h"
0026 #include <memory>
0027
0028 namespace llvm {
0029
0030 namespace object {
0031
0032
0033 enum OffloadKind : uint16_t {
0034 OFK_None = 0,
0035 OFK_OpenMP,
0036 OFK_Cuda,
0037 OFK_HIP,
0038 OFK_LAST,
0039 };
0040
0041
0042 enum ImageKind : uint16_t {
0043 IMG_None = 0,
0044 IMG_Object,
0045 IMG_Bitcode,
0046 IMG_Cubin,
0047 IMG_Fatbinary,
0048 IMG_PTX,
0049 IMG_LAST,
0050 };
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061 class OffloadBinary : public Binary {
0062 public:
0063 using string_iterator = MapVector<StringRef, StringRef>::const_iterator;
0064 using string_iterator_range = iterator_range<string_iterator>;
0065
0066
0067 static const uint32_t Version = 1;
0068
0069
0070 struct OffloadingImage {
0071 ImageKind TheImageKind;
0072 OffloadKind TheOffloadKind;
0073 uint32_t Flags;
0074 MapVector<StringRef, StringRef> StringData;
0075 std::unique_ptr<MemoryBuffer> Image;
0076 };
0077
0078
0079 static Expected<std::unique_ptr<OffloadBinary>> create(MemoryBufferRef);
0080
0081
0082 static SmallString<0> write(const OffloadingImage &);
0083
0084 static uint64_t getAlignment() { return 8; }
0085
0086 ImageKind getImageKind() const { return TheEntry->TheImageKind; }
0087 OffloadKind getOffloadKind() const { return TheEntry->TheOffloadKind; }
0088 uint32_t getVersion() const { return TheHeader->Version; }
0089 uint32_t getFlags() const { return TheEntry->Flags; }
0090 uint64_t getSize() const { return TheHeader->Size; }
0091
0092 StringRef getTriple() const { return getString("triple"); }
0093 StringRef getArch() const { return getString("arch"); }
0094 StringRef getImage() const {
0095 return StringRef(&Buffer[TheEntry->ImageOffset], TheEntry->ImageSize);
0096 }
0097
0098
0099 string_iterator_range strings() const {
0100 return string_iterator_range(StringData.begin(), StringData.end());
0101 }
0102
0103 StringRef getString(StringRef Key) const { return StringData.lookup(Key); }
0104
0105 static bool classof(const Binary *V) { return V->isOffloadFile(); }
0106
0107 struct Header {
0108 uint8_t Magic[4] = {0x10, 0xFF, 0x10, 0xAD};
0109 uint32_t Version = OffloadBinary::Version;
0110 uint64_t Size;
0111 uint64_t EntryOffset;
0112 uint64_t EntrySize;
0113 };
0114
0115 struct Entry {
0116 ImageKind TheImageKind;
0117 OffloadKind TheOffloadKind;
0118 uint32_t Flags;
0119 uint64_t StringOffset;
0120 uint64_t NumStrings;
0121 uint64_t ImageOffset;
0122 uint64_t ImageSize;
0123 };
0124
0125 struct StringEntry {
0126 uint64_t KeyOffset;
0127 uint64_t ValueOffset;
0128 };
0129
0130 private:
0131 OffloadBinary(MemoryBufferRef Source, const Header *TheHeader,
0132 const Entry *TheEntry)
0133 : Binary(Binary::ID_Offload, Source), Buffer(Source.getBufferStart()),
0134 TheHeader(TheHeader), TheEntry(TheEntry) {
0135 const StringEntry *StringMapBegin =
0136 reinterpret_cast<const StringEntry *>(&Buffer[TheEntry->StringOffset]);
0137 for (uint64_t I = 0, E = TheEntry->NumStrings; I != E; ++I) {
0138 StringRef Key = &Buffer[StringMapBegin[I].KeyOffset];
0139 StringData[Key] = &Buffer[StringMapBegin[I].ValueOffset];
0140 }
0141 }
0142
0143 OffloadBinary(const OffloadBinary &Other) = delete;
0144
0145
0146 MapVector<StringRef, StringRef> StringData;
0147
0148 const char *Buffer;
0149
0150 const Header *TheHeader;
0151
0152 const Entry *TheEntry;
0153 };
0154
0155
0156
0157 class OffloadFile : public OwningBinary<OffloadBinary> {
0158 public:
0159 using TargetID = std::pair<StringRef, StringRef>;
0160
0161 OffloadFile(std::unique_ptr<OffloadBinary> Binary,
0162 std::unique_ptr<MemoryBuffer> Buffer)
0163 : OwningBinary<OffloadBinary>(std::move(Binary), std::move(Buffer)) {}
0164
0165
0166 OffloadFile copy() const {
0167 std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBufferCopy(
0168 getBinary()->getMemoryBufferRef().getBuffer(),
0169 getBinary()->getMemoryBufferRef().getBufferIdentifier());
0170
0171
0172 auto NewBinaryOrErr = OffloadBinary::create(*Buffer);
0173 assert(NewBinaryOrErr && "Failed to parse a copy of the binary?");
0174 if (!NewBinaryOrErr)
0175 llvm::consumeError(NewBinaryOrErr.takeError());
0176 return OffloadFile(std::move(*NewBinaryOrErr), std::move(Buffer));
0177 }
0178
0179
0180
0181 operator TargetID() const {
0182 return std::make_pair(getBinary()->getTriple(), getBinary()->getArch());
0183 }
0184 };
0185
0186
0187
0188 Error extractOffloadBinaries(MemoryBufferRef Buffer,
0189 SmallVectorImpl<OffloadFile> &Binaries);
0190
0191
0192 ImageKind getImageKind(StringRef Name);
0193
0194
0195 StringRef getImageKindName(ImageKind Name);
0196
0197
0198 OffloadKind getOffloadKind(StringRef Name);
0199
0200
0201 StringRef getOffloadKindName(OffloadKind Name);
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212 bool areTargetsCompatible(const OffloadFile::TargetID &LHS,
0213 const OffloadFile::TargetID &RHS);
0214
0215 }
0216
0217 }
0218 #endif