#ifndef LLVM_OBJECT_OFFLOADBINARY_H
#define LLVM_OBJECT_OFFLOADBINARY_H
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/Binary.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"
#include <memory>
namespace llvm {
namespace object {
enum OffloadKind : uint16_t {
OFK_None = 0,
OFK_OpenMP,
OFK_Cuda,
OFK_HIP,
OFK_LAST,
};
enum ImageKind : uint16_t {
IMG_None = 0,
IMG_Object,
IMG_Bitcode,
IMG_Cubin,
IMG_Fatbinary,
IMG_PTX,
IMG_LAST,
};
class OffloadBinary : public Binary {
public:
using string_iterator = StringMap<StringRef>::const_iterator;
using string_iterator_range = iterator_range<string_iterator>;
static const uint32_t Version = 1;
struct OffloadingImage {
ImageKind TheImageKind;
OffloadKind TheOffloadKind;
uint32_t Flags;
StringMap<StringRef> StringData;
std::unique_ptr<MemoryBuffer> Image;
};
static Expected<std::unique_ptr<OffloadBinary>> create(MemoryBufferRef);
static std::unique_ptr<MemoryBuffer> write(const OffloadingImage &);
static uint64_t getAlignment() { return 8; }
ImageKind getImageKind() const { return TheEntry->TheImageKind; }
OffloadKind getOffloadKind() const { return TheEntry->TheOffloadKind; }
uint32_t getVersion() const { return TheHeader->Version; }
uint32_t getFlags() const { return TheEntry->Flags; }
uint64_t getSize() const { return TheHeader->Size; }
StringRef getTriple() const { return getString("triple"); }
StringRef getArch() const { return getString("arch"); }
StringRef getImage() const {
return StringRef(&Buffer[TheEntry->ImageOffset], TheEntry->ImageSize);
}
string_iterator_range strings() const {
return string_iterator_range(StringData.begin(), StringData.end());
}
StringRef getString(StringRef Key) const { return StringData.lookup(Key); }
static bool classof(const Binary *V) { return V->isOffloadFile(); }
struct Header {
uint8_t Magic[4] = {0x10, 0xFF, 0x10, 0xAD}; uint32_t Version = OffloadBinary::Version; uint64_t Size; uint64_t EntryOffset; uint64_t EntrySize; };
struct Entry {
ImageKind TheImageKind; OffloadKind TheOffloadKind; uint32_t Flags; uint64_t StringOffset; uint64_t NumStrings; uint64_t ImageOffset; uint64_t ImageSize; };
struct StringEntry {
uint64_t KeyOffset;
uint64_t ValueOffset;
};
private:
OffloadBinary(MemoryBufferRef Source, const Header *TheHeader,
const Entry *TheEntry)
: Binary(Binary::ID_Offload, Source), Buffer(Source.getBufferStart()),
TheHeader(TheHeader), TheEntry(TheEntry) {
const StringEntry *StringMapBegin =
reinterpret_cast<const StringEntry *>(&Buffer[TheEntry->StringOffset]);
for (uint64_t I = 0, E = TheEntry->NumStrings; I != E; ++I) {
StringRef Key = &Buffer[StringMapBegin[I].KeyOffset];
StringData[Key] = &Buffer[StringMapBegin[I].ValueOffset];
}
}
OffloadBinary(const OffloadBinary &Other) = delete;
StringMap<StringRef> StringData;
const char *Buffer;
const Header *TheHeader;
const Entry *TheEntry;
};
ImageKind getImageKind(StringRef Name);
StringRef getImageKindName(ImageKind Name);
OffloadKind getOffloadKind(StringRef Name);
StringRef getOffloadKindName(OffloadKind Name);
}
} #endif