forked from OSchip/llvm-project
[Binary] Promote OffloadBinary to inherit from Binary
We use the `OffloadBinary` to create binary images of offloading files and their corresonding metadata. This patch changes this to inherit from the base `Binary` class. This allows us to create and insepect these more generically. This patch includes all the necessary glue to implement this as a new binary format, along with added the magic bytes we use to distinguish the offloading binary to the `file_magic` implementation. Reviewed By: tra Differential Revision: https://reviews.llvm.org/D126812
This commit is contained in:
parent
909a78b3a4
commit
afd2f7e991
|
@ -1221,6 +1221,6 @@ void clang::EmbedObject(llvm::Module *M, const CodeGenOptions &CGOpts,
|
|||
}
|
||||
|
||||
llvm::embedBufferInModule(*M, **ObjectOrErr, ".llvm.offloading",
|
||||
Align(OffloadBinary::getAlignment()));
|
||||
Align(object::OffloadBinary::getAlignment()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,21 +38,23 @@ typedef struct LLVMOpaqueSymbolIterator *LLVMSymbolIteratorRef;
|
|||
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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -52,6 +52,7 @@ struct file_magic {
|
|||
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
|
||||
};
|
||||
|
||||
|
|
|
@ -69,6 +69,8 @@ protected:
|
|||
|
||||
ID_Wasm,
|
||||
|
||||
ID_Offload, // Offloading binary file.
|
||||
|
||||
ID_EndObjects
|
||||
};
|
||||
|
||||
|
@ -133,6 +135,8 @@ public:
|
|||
|
||||
bool isWasm() const { return TypeID == ID_Wasm; }
|
||||
|
||||
bool isOffloadFile() const { return TypeID == ID_Offload; }
|
||||
|
||||
bool isCOFFImportFile() const {
|
||||
return TypeID == ID_COFFImportFile;
|
||||
}
|
||||
|
|
|
@ -19,12 +19,15 @@
|
|||
|
||||
#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,
|
||||
|
@ -54,7 +57,7 @@ enum ImageKind : uint16_t {
|
|||
/// 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 {
|
||||
|
@ -87,6 +90,8 @@ public:
|
|||
|
||||
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.
|
||||
|
@ -111,10 +116,10 @@ private:
|
|||
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) {
|
||||
|
@ -127,7 +132,7 @@ private:
|
|||
|
||||
/// 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;
|
||||
|
@ -147,5 +152,7 @@ OffloadKind getOffloadKind(StringRef Name);
|
|||
/// Convert an offload kind to its string representation.
|
||||
StringRef getOffloadKindName(OffloadKind Name);
|
||||
|
||||
} // namespace object
|
||||
|
||||
} // namespace llvm
|
||||
#endif
|
||||
|
|
|
@ -74,6 +74,11 @@ file_magic llvm::identify_magic(StringRef Magic) {
|
|||
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;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#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"
|
||||
|
@ -87,6 +88,8 @@ Expected<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer,
|
|||
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:
|
||||
|
|
|
@ -120,6 +120,8 @@ LLVMBinaryType LLVMBinaryGetType(LLVMBinaryRef BR) {
|
|||
return LLVMBinaryTypeMachO64L;
|
||||
case ID_MachO64B:
|
||||
return LLVMBinaryTypeMachO64B;
|
||||
case ID_Offload:
|
||||
return LLVMBinaryTypeOffload;
|
||||
case ID_Wasm:
|
||||
return LLVMBinaryTypeWasm;
|
||||
case ID_StartObjects:
|
||||
|
|
|
@ -147,6 +147,7 @@ ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type,
|
|||
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:
|
||||
|
|
|
@ -9,22 +9,23 @@
|
|||
#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);
|
||||
|
@ -32,7 +33,7 @@ OffloadBinary::create(MemoryBufferRef Buf) {
|
|||
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>
|
||||
|
@ -141,4 +142,6 @@ StringRef getImageKindName(ImageKind Kind) {
|
|||
}
|
||||
}
|
||||
|
||||
} // namespace object
|
||||
|
||||
} // namespace llvm
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
#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{}());
|
||||
|
@ -27,23 +30,22 @@ TEST(OffloadingTest, checkOffloadingBinary) {
|
|||
}
|
||||
|
||||
// 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();
|
||||
|
||||
|
@ -60,6 +62,6 @@ TEST(OffloadingTest, checkOffloadingBinary) {
|
|||
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());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue