}
llvm::embedBufferInModule(*M, **ObjectOrErr, ".llvm.offloading",
- Align(OffloadBinary::getAlignment()));
+ Align(object::OffloadBinary::getAlignment()));
}
}
typedef struct LLVMOpaqueRelocationIterator *LLVMRelocationIteratorRef;
typedef enum {
- LLVMBinaryTypeArchive, /**< Archive file. */
- LLVMBinaryTypeMachOUniversalBinary, /**< Mach-O Universal Binary file. */
- LLVMBinaryTypeCOFFImportFile, /**< COFF Import file. */
- LLVMBinaryTypeIR, /**< LLVM IR. */
- LLVMBinaryTypeWinRes, /**< Windows resource (.res) file. */
- LLVMBinaryTypeCOFF, /**< COFF Object file. */
- LLVMBinaryTypeELF32L, /**< ELF 32-bit, little endian. */
- LLVMBinaryTypeELF32B, /**< ELF 32-bit, big endian. */
- LLVMBinaryTypeELF64L, /**< ELF 64-bit, little endian. */
- LLVMBinaryTypeELF64B, /**< ELF 64-bit, big endian. */
- LLVMBinaryTypeMachO32L, /**< MachO 32-bit, little endian. */
- LLVMBinaryTypeMachO32B, /**< MachO 32-bit, big endian. */
- LLVMBinaryTypeMachO64L, /**< MachO 64-bit, little endian. */
- LLVMBinaryTypeMachO64B, /**< MachO 64-bit, big endian. */
- LLVMBinaryTypeWasm, /**< Web Assembly. */
+ LLVMBinaryTypeArchive, /**< Archive file. */
+ LLVMBinaryTypeMachOUniversalBinary, /**< Mach-O Universal Binary file. */
+ LLVMBinaryTypeCOFFImportFile, /**< COFF Import file. */
+ LLVMBinaryTypeIR, /**< LLVM IR. */
+ LLVMBinaryTypeWinRes, /**< Windows resource (.res) file. */
+ LLVMBinaryTypeCOFF, /**< COFF Object file. */
+ LLVMBinaryTypeELF32L, /**< ELF 32-bit, little endian. */
+ LLVMBinaryTypeELF32B, /**< ELF 32-bit, big endian. */
+ LLVMBinaryTypeELF64L, /**< ELF 64-bit, little endian. */
+ LLVMBinaryTypeELF64B, /**< ELF 64-bit, big endian. */
+ LLVMBinaryTypeMachO32L, /**< MachO 32-bit, little endian. */
+ LLVMBinaryTypeMachO32B, /**< MachO 32-bit, big endian. */
+ LLVMBinaryTypeMachO64L, /**< MachO 64-bit, little endian. */
+ LLVMBinaryTypeMachO64B, /**< MachO 64-bit, big endian. */
+ LLVMBinaryTypeWasm, /**< Web Assembly. */
+ LLVMBinaryTypeOffload, /**< Offloading fatbinary. */
+
} LLVMBinaryType;
/**
pdb, ///< Windows PDB debug info file
tapi_file, ///< Text-based Dynamic Library Stub file
cuda_fatbinary, ///< CUDA Fatbinary object file
+ offload_binary, ///< LLVM offload object file
dxcontainer_object, ///< DirectX container file
};
ID_Wasm,
+ ID_Offload, // Offloading binary file.
+
ID_EndObjects
};
bool isWasm() const { return TypeID == ID_Wasm; }
+ bool isOffloadFile() const { return TypeID == ID_Offload; }
+
bool isCOFFImportFile() const {
return TypeID == ID_COFFImportFile;
}
#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 {
+
/// The producer of the associated offloading image.
enum OffloadKind : uint16_t {
OFK_None = 0,
/// detect ABI stability and the size is used to find other offloading entries
/// that may exist in the same section. All offsets are given as absolute byte
/// offsets from the beginning of the file.
-class OffloadBinary {
+class OffloadBinary : public Binary {
public:
/// The offloading metadata that will be serialized to a memory buffer.
struct OffloadingImage {
StringRef getString(StringRef Key) const { return StringData.lookup(Key); }
+ static bool classof(const Binary *V) { return V->isOffloadFile(); }
+
private:
struct Header {
uint8_t Magic[4] = {0x10, 0xFF, 0x10, 0xAD}; // 0x10FF10AD magic bytes.
uint64_t ValueOffset;
};
- OffloadBinary(const char *Buffer, const Header *TheHeader,
+ OffloadBinary(MemoryBufferRef Source, const Header *TheHeader,
const Entry *TheEntry)
- : Buffer(Buffer), TheHeader(TheHeader), TheEntry(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) {
/// Map from keys to offsets in the binary.
StringMap<StringRef> StringData;
- /// Pointer to the beginning of the memory buffer for convenience.
+ /// Raw pointer to the MemoryBufferRef for convenience.
const char *Buffer;
/// Location of the header within the binary.
const Header *TheHeader;
/// Convert an offload kind to its string representation.
StringRef getOffloadKindName(OffloadKind Name);
+} // namespace object
+
} // namespace llvm
#endif
return file_magic::goff_object;
break;
+ case 0x10:
+ if (startswith(Magic, "\x10\xFF\x10\xAD"))
+ return file_magic::offload_binary;
+ break;
+
case 0xDE: // 0x0B17C0DE = BC wraper
if (startswith(Magic, "\xDE\xC0\x17\x0B"))
return file_magic::bitcode;
#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/Minidump.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/OffloadBinary.h"
#include "llvm/Object/TapiUniversal.h"
#include "llvm/Object/WindowsResource.h"
#include "llvm/Support/Error.h"
case file_magic::dxcontainer_object:
// Unrecognized object file format.
return errorCodeToError(object_error::invalid_file_type);
+ case file_magic::offload_binary:
+ return OffloadBinary::create(Buffer);
case file_magic::minidump:
return MinidumpFile::create(Buffer);
case file_magic::tapi_file:
return LLVMBinaryTypeMachO64L;
case ID_MachO64B:
return LLVMBinaryTypeMachO64B;
+ case ID_Offload:
+ return LLVMBinaryTypeOffload;
case ID_Wasm:
return LLVMBinaryTypeWasm;
case ID_StartObjects:
case file_magic::minidump:
case file_magic::goff_object:
case file_magic::cuda_fatbinary:
+ case file_magic::offload_binary:
case file_magic::dxcontainer_object:
return errorCodeToError(object_error::invalid_file_type);
case file_magic::tapi_file:
#include "llvm/Object/OffloadBinary.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/BinaryFormat/Magic.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Object/Error.h"
#include "llvm/Support/FileOutputBuffer.h"
-using namespace llvm;
-
namespace llvm {
+namespace object {
+
Expected<std::unique_ptr<OffloadBinary>>
OffloadBinary::create(MemoryBufferRef Buf) {
if (Buf.getBufferSize() < sizeof(Header) + sizeof(Entry))
- return errorCodeToError(llvm::object::object_error::parse_failed);
+ return errorCodeToError(object_error::parse_failed);
// Check for 0x10FF1OAD magic bytes.
- if (!Buf.getBuffer().startswith("\x10\xFF\x10\xAD"))
- return errorCodeToError(llvm::object::object_error::parse_failed);
+ if (identify_magic(Buf.getBuffer()) != file_magic::offload_binary)
+ return errorCodeToError(object_error::parse_failed);
const char *Start = Buf.getBufferStart();
const Header *TheHeader = reinterpret_cast<const Header *>(Start);
reinterpret_cast<const Entry *>(&Start[TheHeader->EntryOffset]);
return std::unique_ptr<OffloadBinary>(
- new OffloadBinary(Buf.getBufferStart(), TheHeader, TheEntry));
+ new OffloadBinary(Buf, TheHeader, TheEntry));
}
std::unique_ptr<MemoryBuffer>
}
}
+} // namespace object
+
} // namespace llvm
#include "gtest/gtest.h"
#include <random>
+using namespace llvm;
+using namespace llvm::object;
+
TEST(OffloadingTest, checkOffloadingBinary) {
// Create random data to fill the image.
std::mt19937 Rng(std::random_device{}());
}
// Create the image.
- llvm::StringMap<llvm::StringRef> StringData;
+ StringMap<StringRef> StringData;
for (auto &KeyAndValue : Strings)
StringData[KeyAndValue.first] = KeyAndValue.second;
- std::unique_ptr<llvm::MemoryBuffer> ImageData =
- llvm::MemoryBuffer::getMemBuffer(
- {reinterpret_cast<char *>(Image.data()), Image.size()}, "", false);
+ std::unique_ptr<MemoryBuffer> ImageData = MemoryBuffer::getMemBuffer(
+ {reinterpret_cast<char *>(Image.data()), Image.size()}, "", false);
- llvm::OffloadBinary::OffloadingImage Data;
- Data.TheImageKind = static_cast<llvm::ImageKind>(KindDist(Rng));
- Data.TheOffloadKind = static_cast<llvm::OffloadKind>(KindDist(Rng));
+ OffloadBinary::OffloadingImage Data;
+ Data.TheImageKind = static_cast<ImageKind>(KindDist(Rng));
+ Data.TheOffloadKind = static_cast<OffloadKind>(KindDist(Rng));
Data.Flags = KindDist(Rng);
Data.StringData = StringData;
Data.Image = *ImageData;
- auto BinaryBuffer = llvm::OffloadBinary::write(Data);
+ auto BinaryBuffer = OffloadBinary::write(Data);
- auto BinaryOrErr = llvm::OffloadBinary::create(*BinaryBuffer);
+ auto BinaryOrErr = OffloadBinary::create(*BinaryBuffer);
if (!BinaryOrErr)
FAIL();
EXPECT_TRUE(Data.Image.getBuffer() == Binary.getImage());
// Ensure the size and alignment of the data is correct.
- EXPECT_TRUE(Binary.getSize() % llvm::OffloadBinary::getAlignment() == 0);
+ EXPECT_TRUE(Binary.getSize() % OffloadBinary::getAlignment() == 0);
EXPECT_TRUE(Binary.getSize() == BinaryBuffer->getBuffer().size());
}