diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -1221,6 +1221,6 @@ } llvm::embedBufferInModule(*M, **ObjectOrErr, ".llvm.offloading", - Align(OffloadBinary::getAlignment())); + Align(object::OffloadBinary::getAlignment())); } } diff --git a/llvm/include/llvm-c/Object.h b/llvm/include/llvm-c/Object.h --- a/llvm/include/llvm-c/Object.h +++ b/llvm/include/llvm-c/Object.h @@ -38,21 +38,23 @@ 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; /** diff --git a/llvm/include/llvm/BinaryFormat/Magic.h b/llvm/include/llvm/BinaryFormat/Magic.h --- a/llvm/include/llvm/BinaryFormat/Magic.h +++ b/llvm/include/llvm/BinaryFormat/Magic.h @@ -52,6 +52,7 @@ 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 }; diff --git a/llvm/include/llvm/Object/Binary.h b/llvm/include/llvm/Object/Binary.h --- a/llvm/include/llvm/Object/Binary.h +++ b/llvm/include/llvm/Object/Binary.h @@ -69,6 +69,8 @@ ID_Wasm, + ID_Offload, // Offloading binary file. + ID_EndObjects }; @@ -133,6 +135,8 @@ bool isWasm() const { return TypeID == ID_Wasm; } + bool isOffloadFile() const { return TypeID == ID_Offload; } + bool isCOFFImportFile() const { return TypeID == ID_COFFImportFile; } diff --git a/llvm/include/llvm/Object/OffloadBinary.h b/llvm/include/llvm/Object/OffloadBinary.h --- a/llvm/include/llvm/Object/OffloadBinary.h +++ b/llvm/include/llvm/Object/OffloadBinary.h @@ -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 namespace llvm { +namespace object { + /// The producer of the associated offloading image. enum OffloadKind : uint16_t { OFK_None = 0, @@ -54,7 +57,7 @@ /// 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 @@ 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,11 @@ 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 char *Buffer = Data.getBufferStart(); const StringEntry *StringMapBegin = reinterpret_cast(&Buffer[TheEntry->StringOffset]); for (uint64_t I = 0, E = TheEntry->NumStrings; I != E; ++I) { @@ -127,7 +133,7 @@ /// Map from keys to offsets in the binary. StringMap 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 +153,7 @@ /// Convert an offload kind to its string representation. StringRef getOffloadKindName(OffloadKind Name); +} // namespace object + } // namespace llvm #endif diff --git a/llvm/lib/BinaryFormat/Magic.cpp b/llvm/lib/BinaryFormat/Magic.cpp --- a/llvm/lib/BinaryFormat/Magic.cpp +++ b/llvm/lib/BinaryFormat/Magic.cpp @@ -74,6 +74,11 @@ 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; diff --git a/llvm/lib/Object/Binary.cpp b/llvm/lib/Object/Binary.cpp --- a/llvm/lib/Object/Binary.cpp +++ b/llvm/lib/Object/Binary.cpp @@ -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 @@ 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: diff --git a/llvm/lib/Object/Object.cpp b/llvm/lib/Object/Object.cpp --- a/llvm/lib/Object/Object.cpp +++ b/llvm/lib/Object/Object.cpp @@ -120,6 +120,8 @@ return LLVMBinaryTypeMachO64L; case ID_MachO64B: return LLVMBinaryTypeMachO64B; + case ID_Offload: + return LLVMBinaryTypeOffload; case ID_Wasm: return LLVMBinaryTypeWasm; case ID_StartObjects: diff --git a/llvm/lib/Object/ObjectFile.cpp b/llvm/lib/Object/ObjectFile.cpp --- a/llvm/lib/Object/ObjectFile.cpp +++ b/llvm/lib/Object/ObjectFile.cpp @@ -147,6 +147,7 @@ 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: diff --git a/llvm/lib/Object/OffloadBinary.cpp b/llvm/lib/Object/OffloadBinary.cpp --- a/llvm/lib/Object/OffloadBinary.cpp +++ b/llvm/lib/Object/OffloadBinary.cpp @@ -9,22 +9,22 @@ #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 { +using namespace object; Expected> 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(Start); @@ -32,7 +32,7 @@ reinterpret_cast(&Start[TheHeader->EntryOffset]); return std::unique_ptr( - new OffloadBinary(Buf.getBufferStart(), TheHeader, TheEntry)); + new OffloadBinary(Buf, TheHeader, TheEntry)); } std::unique_ptr @@ -93,7 +93,7 @@ return MemoryBuffer::getMemBufferCopy(OS.str()); } -OffloadKind getOffloadKind(StringRef Name) { +OffloadKind llvm::object::getOffloadKind(StringRef Name) { return llvm::StringSwitch(Name) .Case("openmp", OFK_OpenMP) .Case("cuda", OFK_Cuda) @@ -101,7 +101,7 @@ .Default(OFK_None); } -StringRef getOffloadKindName(OffloadKind Kind) { +StringRef llvm::object::getOffloadKindName(OffloadKind Kind) { switch (Kind) { case OFK_OpenMP: return "openmp"; @@ -114,7 +114,7 @@ } } -ImageKind getImageKind(StringRef Name) { +ImageKind llvm::object::getImageKind(StringRef Name) { return llvm::StringSwitch(Name) .Case("o", IMG_Object) .Case("bc", IMG_Bitcode) @@ -124,7 +124,7 @@ .Default(IMG_None); } -StringRef getImageKindName(ImageKind Kind) { +StringRef llvm::object::getImageKindName(ImageKind Kind) { switch (Kind) { case IMG_Object: return "o"; @@ -140,5 +140,3 @@ return ""; } } - -} // namespace llvm diff --git a/llvm/unittests/Object/OffloadingTest.cpp b/llvm/unittests/Object/OffloadingTest.cpp --- a/llvm/unittests/Object/OffloadingTest.cpp +++ b/llvm/unittests/Object/OffloadingTest.cpp @@ -4,6 +4,9 @@ #include "gtest/gtest.h" #include +using namespace llvm; +using namespace object; + TEST(OffloadingTest, checkOffloadingBinary) { // Create random data to fill the image. std::mt19937 Rng(std::random_device{}()); @@ -27,23 +30,22 @@ } // Create the image. - llvm::StringMap StringData; + StringMap StringData; for (auto &KeyAndValue : Strings) StringData[KeyAndValue.first] = KeyAndValue.second; - std::unique_ptr ImageData = - llvm::MemoryBuffer::getMemBuffer( - {reinterpret_cast(Image.data()), Image.size()}, "", false); + std::unique_ptr ImageData = MemoryBuffer::getMemBuffer( + {reinterpret_cast(Image.data()), Image.size()}, "", false); - llvm::OffloadBinary::OffloadingImage Data; - Data.TheImageKind = static_cast(KindDist(Rng)); - Data.TheOffloadKind = static_cast(KindDist(Rng)); + OffloadBinary::OffloadingImage Data; + Data.TheImageKind = static_cast(KindDist(Rng)); + Data.TheOffloadKind = static_cast(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 @@ 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()); }