[llvm] Fix compress/decompress in LLVM Offloading API (PR #150064)
David Salinas via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 18 12:57:53 PDT 2025
https://github.com/david-salinas updated https://github.com/llvm/llvm-project/pull/150064
>From 8fd5968e77eab62bd000f42590bde1cda5c1ea89 Mon Sep 17 00:00:00 2001
From: dsalinas_amdeng <david.salinas at amd.com>
Date: Tue, 17 Jun 2025 19:03:35 +0000
Subject: [PATCH 1/8] SWDEV-52811 - fix compress/decompress in LLVM Offloading
API
---
llvm/include/llvm/Object/OffloadBundle.h | 79 ++--
llvm/lib/Object/OffloadBundle.cpp | 485 +++++++++++++++--------
llvm/tools/llvm-objdump/OffloadDump.cpp | 27 +-
3 files changed, 391 insertions(+), 200 deletions(-)
diff --git a/llvm/include/llvm/Object/OffloadBundle.h b/llvm/include/llvm/Object/OffloadBundle.h
index f4d5a1d878b8d..99f54ea4f28aa 100644
--- a/llvm/include/llvm/Object/OffloadBundle.h
+++ b/llvm/include/llvm/Object/OffloadBundle.h
@@ -32,29 +32,40 @@ namespace llvm {
namespace object {
+// CompressedOffloadBundle represents the format for the compressed offload
+// bundles.
+//
+// The format is as follows:
+// - Magic Number (4 bytes) - A constant "CCOB".
+// - Version (2 bytes)
+// - Compression Method (2 bytes) - Uses the values from
+// llvm::compression::Format.
+// - Total file size (4 bytes in V2, 8 bytes in V3).
+// - Uncompressed Size (4 bytes in V1/V2, 8 bytes in V3).
+// - Truncated MD5 Hash (8 bytes).
+// - Compressed Data (variable length).
class CompressedOffloadBundle {
private:
- static inline const size_t MagicSize = 4;
- static inline const size_t VersionFieldSize = sizeof(uint16_t);
- static inline const size_t MethodFieldSize = sizeof(uint16_t);
- static inline const size_t FileSizeFieldSize = sizeof(uint32_t);
- static inline const size_t UncompressedSizeFieldSize = sizeof(uint32_t);
- static inline const size_t HashFieldSize = sizeof(uint64_t);
- static inline const size_t V1HeaderSize =
- MagicSize + VersionFieldSize + MethodFieldSize +
- UncompressedSizeFieldSize + HashFieldSize;
- static inline const size_t V2HeaderSize =
- MagicSize + VersionFieldSize + FileSizeFieldSize + MethodFieldSize +
- UncompressedSizeFieldSize + HashFieldSize;
static inline const llvm::StringRef MagicNumber = "CCOB";
- static inline const uint16_t Version = 2;
public:
- LLVM_ABI static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
+ struct CompressedBundleHeader {
+ unsigned Version;
+ llvm::compression::Format CompressionFormat;
+ std::optional<size_t> FileSize;
+ size_t UncompressedFileSize;
+ uint64_t Hash;
+
+ static llvm::Expected<CompressedBundleHeader> tryParse(llvm::StringRef);
+ };
+
+ static inline const uint16_t DefaultVersion = 2;
+
+ static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
compress(llvm::compression::Params P, const llvm::MemoryBuffer &Input,
- bool Verbose = false);
- LLVM_ABI static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
- decompress(llvm::MemoryBufferRef &Input, bool Verbose = false);
+ uint16_t Version, bool Verbose = false);
+ static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
+ decompress(const llvm::MemoryBuffer &Input, bool Verbose = false);
};
/// Bundle entry in binary clang-offload-bundler format.
@@ -62,12 +73,15 @@ struct OffloadBundleEntry {
uint64_t Offset = 0u;
uint64_t Size = 0u;
uint64_t IDLength = 0u;
- StringRef ID;
- OffloadBundleEntry(uint64_t O, uint64_t S, uint64_t I, StringRef T)
- : Offset(O), Size(S), IDLength(I), ID(T) {}
+ std::string ID;
+ OffloadBundleEntry(uint64_t O, uint64_t S, uint64_t I, std::string T)
+ : Offset(O), Size(S), IDLength(I) {
+ ID.reserve(T.size());
+ ID = T;
+ }
void dumpInfo(raw_ostream &OS) {
OS << "Offset = " << Offset << ", Size = " << Size
- << ", ID Length = " << IDLength << ", ID = " << ID;
+ << ", ID Length = " << IDLength << ", ID = " << ID << "\n";
}
void dumpURI(raw_ostream &OS, StringRef FilePath) {
OS << ID.data() << "\tfile://" << FilePath << "#offset=" << Offset
@@ -82,15 +96,20 @@ class OffloadBundleFatBin {
StringRef FileName;
uint64_t NumberOfEntries;
SmallVector<OffloadBundleEntry> Entries;
+ bool Decompressed;
public:
+ std::unique_ptr<MemoryBuffer> DecompressedBuffer;
+
SmallVector<OffloadBundleEntry> getEntries() { return Entries; }
uint64_t getSize() const { return Size; }
StringRef getFileName() const { return FileName; }
uint64_t getNumEntries() const { return NumberOfEntries; }
+ bool isDecompressed() const { return Decompressed; }
LLVM_ABI static Expected<std::unique_ptr<OffloadBundleFatBin>>
- create(MemoryBufferRef, uint64_t SectionOffset, StringRef FileName);
+ create(MemoryBufferRef, uint64_t SectionOffset, StringRef FileName,
+ bool Decompress = false);
LLVM_ABI Error extractBundle(const ObjectFile &Source);
LLVM_ABI Error dumpEntryToCodeObject();
@@ -106,9 +125,15 @@ class OffloadBundleFatBin {
Entry.dumpURI(outs(), FileName);
}
- OffloadBundleFatBin(MemoryBufferRef Source, StringRef File)
- : FileName(File), NumberOfEntries(0),
- Entries(SmallVector<OffloadBundleEntry>()) {}
+ OffloadBundleFatBin(MemoryBufferRef Source, StringRef File,
+ bool Decompress = false)
+ : FileName(File), Decompressed(Decompress), NumberOfEntries(0),
+ Entries(SmallVector<OffloadBundleEntry>()) {
+ if (Decompress) {
+ DecompressedBuffer =
+ MemoryBuffer::getMemBufferCopy(Source.getBuffer(), File);
+ }
+ }
};
enum UriTypeT { FILE_URI, MEMORY_URI };
@@ -191,6 +216,10 @@ LLVM_ABI Error extractOffloadBundleFatBinary(
LLVM_ABI Error extractCodeObject(const ObjectFile &Source, int64_t Offset,
int64_t Size, StringRef OutputFileName);
+/// Extract code object memory from the given \p Source object file at \p Offset
+/// and of \p Size, and copy into \p OutputFileName.
+LLVM_ABI Error extractCodeObject(MemoryBufferRef Buffer, int64_t Offset,
+ int64_t Size, StringRef OutputFileName);
/// Extracts an Offload Bundle Entry given by URI
LLVM_ABI Error extractOffloadBundleByURI(StringRef URIstr);
diff --git a/llvm/lib/Object/OffloadBundle.cpp b/llvm/lib/Object/OffloadBundle.cpp
index 1e1042ce2bc21..57a8244a9b0e5 100644
--- a/llvm/lib/Object/OffloadBundle.cpp
+++ b/llvm/lib/Object/OffloadBundle.cpp
@@ -37,26 +37,63 @@ Error extractOffloadBundle(MemoryBufferRef Contents, uint64_t SectionOffset,
size_t Offset = 0;
size_t NextbundleStart = 0;
+ StringRef Magic;
+ std::unique_ptr<MemoryBuffer> Buffer;
// There could be multiple offloading bundles stored at this section.
- while (NextbundleStart != StringRef::npos) {
- std::unique_ptr<MemoryBuffer> Buffer =
+ while ((NextbundleStart != StringRef::npos) &&
+ (Offset < Contents.getBuffer().size())) {
+ Buffer =
MemoryBuffer::getMemBuffer(Contents.getBuffer().drop_front(Offset), "",
/*RequiresNullTerminator=*/false);
- // Create the FatBinBindle object. This will also create the Bundle Entry
- // list info.
- auto FatBundleOrErr =
- OffloadBundleFatBin::create(*Buffer, SectionOffset + Offset, FileName);
- if (!FatBundleOrErr)
- return FatBundleOrErr.takeError();
-
- // Add current Bundle to list.
- Bundles.emplace_back(std::move(**FatBundleOrErr));
+ if (identify_magic((*Buffer).getBuffer()) ==
+ file_magic::offload_bundle_compressed) {
+ Magic = StringRef("CCOB");
+ // decompress this bundle first.
+ NextbundleStart = (*Buffer).getBuffer().find(Magic, Magic.size());
+ if (NextbundleStart == StringRef::npos) {
+ NextbundleStart = (*Buffer).getBuffer().size();
+ }
- // Find the next bundle by searching for the magic string
- StringRef Str = Buffer->getBuffer();
- NextbundleStart = Str.find(StringRef("__CLANG_OFFLOAD_BUNDLE__"), 24);
+ ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
+ MemoryBuffer::getMemBuffer((*Buffer).getBuffer().take_front(
+ NextbundleStart /*- Magic.size()*/),
+ FileName, false);
+ if (std::error_code EC = CodeOrErr.getError())
+ return createFileError(FileName, EC);
+
+ Expected<std::unique_ptr<MemoryBuffer>> DecompressedBufferOrErr =
+ CompressedOffloadBundle::decompress(**CodeOrErr, false);
+ if (!DecompressedBufferOrErr)
+ return createStringError(
+ inconvertibleErrorCode(),
+ "Failed to decompress input: " +
+ llvm::toString(DecompressedBufferOrErr.takeError()));
+
+ auto FatBundleOrErr = OffloadBundleFatBin::create(
+ **DecompressedBufferOrErr, Offset, FileName, true);
+ if (!FatBundleOrErr)
+ return FatBundleOrErr.takeError();
+
+ // Add current Bundle to list.
+ Bundles.emplace_back(std::move(**FatBundleOrErr));
+
+ } else if (identify_magic((*Buffer).getBuffer()) ==
+ file_magic::offload_bundle) {
+ // Create the FatBinBindle object. This will also create the Bundle Entry
+ // list info.
+ auto FatBundleOrErr = OffloadBundleFatBin::create(
+ *Buffer, SectionOffset + Offset, FileName);
+ if (!FatBundleOrErr)
+ return FatBundleOrErr.takeError();
+
+ // Add current Bundle to list.
+ Bundles.emplace_back(std::move(**FatBundleOrErr));
+
+ Magic = StringRef("__CLANG_OFFLOAD_BUNDLE__");
+ NextbundleStart = (*Buffer).getBuffer().find(Magic, Magic.size());
+ }
if (NextbundleStart != StringRef::npos)
Offset += NextbundleStart;
@@ -102,7 +139,8 @@ Error OffloadBundleFatBin::readEntries(StringRef Buffer,
return errorCodeToError(object_error::parse_failed);
auto Entry = std::make_unique<OffloadBundleEntry>(
- EntryOffset + SectionOffset, EntrySize, EntryIDSize, EntryID);
+ EntryOffset + SectionOffset, EntrySize, EntryIDSize,
+ std::move(EntryID.str()));
Entries.push_back(*Entry);
}
@@ -112,18 +150,22 @@ Error OffloadBundleFatBin::readEntries(StringRef Buffer,
Expected<std::unique_ptr<OffloadBundleFatBin>>
OffloadBundleFatBin::create(MemoryBufferRef Buf, uint64_t SectionOffset,
- StringRef FileName) {
+ StringRef FileName, bool Decompress) {
if (Buf.getBufferSize() < 24)
return errorCodeToError(object_error::parse_failed);
// Check for magic bytes.
- if (identify_magic(Buf.getBuffer()) != file_magic::offload_bundle)
+ if ((identify_magic(Buf.getBuffer()) != file_magic::offload_bundle) &&
+ (identify_magic(Buf.getBuffer()) !=
+ file_magic::offload_bundle_compressed))
return errorCodeToError(object_error::parse_failed);
- OffloadBundleFatBin *TheBundle = new OffloadBundleFatBin(Buf, FileName);
+ OffloadBundleFatBin *TheBundle =
+ new OffloadBundleFatBin(Buf, FileName, Decompress);
// Read the Bundle Entries
- Error Err = TheBundle->readEntries(Buf.getBuffer(), SectionOffset);
+ Error Err =
+ TheBundle->readEntries(Buf.getBuffer(), Decompress ? 0 : SectionOffset);
if (Err)
return errorCodeToError(object_error::parse_failed);
@@ -172,28 +214,9 @@ Error object::extractOffloadBundleFatBinary(
"COFF object files not supported.\n");
MemoryBufferRef Contents(*Buffer, Obj.getFileName());
-
- if (llvm::identify_magic(*Buffer) ==
- llvm::file_magic::offload_bundle_compressed) {
- // Decompress the input if necessary.
- Expected<std::unique_ptr<MemoryBuffer>> DecompressedBufferOrErr =
- CompressedOffloadBundle::decompress(Contents, false);
-
- if (!DecompressedBufferOrErr)
- return createStringError(
- inconvertibleErrorCode(),
- "Failed to decompress input: " +
- llvm::toString(DecompressedBufferOrErr.takeError()));
-
- MemoryBuffer &DecompressedInput = **DecompressedBufferOrErr;
- if (Error Err = extractOffloadBundle(DecompressedInput, SectionOffset,
- Obj.getFileName(), Bundles))
- return Err;
- } else {
- if (Error Err = extractOffloadBundle(Contents, SectionOffset,
- Obj.getFileName(), Bundles))
- return Err;
- }
+ if (Error Err = extractOffloadBundle(Contents, SectionOffset,
+ Obj.getFileName(), Bundles))
+ return Err;
}
}
return Error::success();
@@ -221,6 +244,22 @@ Error object::extractCodeObject(const ObjectFile &Source, int64_t Offset,
return Error::success();
}
+Error object::extractCodeObject(const MemoryBufferRef Buffer, int64_t Offset,
+ int64_t Size, StringRef OutputFileName) {
+ Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
+ FileOutputBuffer::create(OutputFileName, Size);
+ if (!BufferOrErr)
+ return BufferOrErr.takeError();
+
+ std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr);
+ std::copy(Buffer.getBufferStart() + Offset,
+ Buffer.getBufferStart() + Offset + Size, Buf->getBufferStart());
+ if (Error E = Buf->commit())
+ return E;
+
+ return Error::success();
+}
+
// given a file name, offset, and size, extract data into a code object file,
// into file <SourceFile>-offset<Offset>-size<Size>.co
Error object::extractOffloadBundleByURI(StringRef URIstr) {
@@ -260,11 +299,233 @@ static std::string formatWithCommas(unsigned long long Value) {
}
llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
-CompressedOffloadBundle::decompress(llvm::MemoryBufferRef &Input,
+CompressedOffloadBundle::compress(llvm::compression::Params P,
+ const llvm::MemoryBuffer &Input,
+ uint16_t Version, bool Verbose) {
+ if (!llvm::compression::zstd::isAvailable() &&
+ !llvm::compression::zlib::isAvailable())
+ return createStringError(llvm::inconvertibleErrorCode(),
+ "Compression not supported");
+ llvm::Timer HashTimer("Hash Calculation Timer", "Hash calculation time",
+ OffloadBundlerTimerGroup);
+ if (Verbose)
+ HashTimer.startTimer();
+ llvm::MD5 Hash;
+ llvm::MD5::MD5Result Result;
+ Hash.update(Input.getBuffer());
+ Hash.final(Result);
+ uint64_t TruncatedHash = Result.low();
+ if (Verbose)
+ HashTimer.stopTimer();
+
+ SmallVector<uint8_t, 0> CompressedBuffer;
+ auto BufferUint8 = llvm::ArrayRef<uint8_t>(
+ reinterpret_cast<const uint8_t *>(Input.getBuffer().data()),
+ Input.getBuffer().size());
+ llvm::Timer CompressTimer("Compression Timer", "Compression time",
+ OffloadBundlerTimerGroup);
+ if (Verbose)
+ CompressTimer.startTimer();
+ llvm::compression::compress(P, BufferUint8, CompressedBuffer);
+ if (Verbose)
+ CompressTimer.stopTimer();
+
+ uint16_t CompressionMethod = static_cast<uint16_t>(P.format);
+
+ // Store sizes in 64-bit variables first
+ uint64_t UncompressedSize64 = Input.getBuffer().size();
+ uint64_t TotalFileSize64;
+
+ // Calculate total file size based on version
+ if (Version == 2) {
+ // For V2, ensure the sizes don't exceed 32-bit limit
+ if (UncompressedSize64 > std::numeric_limits<uint32_t>::max())
+ return createStringError(llvm::inconvertibleErrorCode(),
+ "Uncompressed size exceeds version 2 limit");
+ if ((MagicNumber.size() + sizeof(uint32_t) + sizeof(Version) +
+ sizeof(CompressionMethod) + sizeof(uint32_t) + sizeof(TruncatedHash) +
+ CompressedBuffer.size()) > std::numeric_limits<uint32_t>::max())
+ return createStringError(llvm::inconvertibleErrorCode(),
+ "Total file size exceeds version 2 limit");
+
+ TotalFileSize64 = MagicNumber.size() + sizeof(uint32_t) + sizeof(Version) +
+ sizeof(CompressionMethod) + sizeof(uint32_t) +
+ sizeof(TruncatedHash) + CompressedBuffer.size();
+ } else { // Version 3
+ TotalFileSize64 = MagicNumber.size() + sizeof(uint64_t) + sizeof(Version) +
+ sizeof(CompressionMethod) + sizeof(uint64_t) +
+ sizeof(TruncatedHash) + CompressedBuffer.size();
+ }
+
+ SmallVector<char, 0> FinalBuffer;
+ llvm::raw_svector_ostream OS(FinalBuffer);
+ OS << MagicNumber;
+ OS.write(reinterpret_cast<const char *>(&Version), sizeof(Version));
+ OS.write(reinterpret_cast<const char *>(&CompressionMethod),
+ sizeof(CompressionMethod));
+
+ // Write size fields according to version
+ if (Version == 2) {
+ uint32_t TotalFileSize32 = static_cast<uint32_t>(TotalFileSize64);
+ uint32_t UncompressedSize32 = static_cast<uint32_t>(UncompressedSize64);
+ OS.write(reinterpret_cast<const char *>(&TotalFileSize32),
+ sizeof(TotalFileSize32));
+ OS.write(reinterpret_cast<const char *>(&UncompressedSize32),
+ sizeof(UncompressedSize32));
+ } else { // Version 3
+ OS.write(reinterpret_cast<const char *>(&TotalFileSize64),
+ sizeof(TotalFileSize64));
+ OS.write(reinterpret_cast<const char *>(&UncompressedSize64),
+ sizeof(UncompressedSize64));
+ }
+
+ OS.write(reinterpret_cast<const char *>(&TruncatedHash),
+ sizeof(TruncatedHash));
+ OS.write(reinterpret_cast<const char *>(CompressedBuffer.data()),
+ CompressedBuffer.size());
+
+ if (Verbose) {
+ auto MethodUsed =
+ P.format == llvm::compression::Format::Zstd ? "zstd" : "zlib";
+ double CompressionRate =
+ static_cast<double>(UncompressedSize64) / CompressedBuffer.size();
+ double CompressionTimeSeconds = CompressTimer.getTotalTime().getWallTime();
+ double CompressionSpeedMBs =
+ (UncompressedSize64 / (1024.0 * 1024.0)) / CompressionTimeSeconds;
+ llvm::errs() << "Compressed bundle format version: " << Version << "\n"
+ << "Total file size (including headers): "
+ << formatWithCommas(TotalFileSize64) << " bytes\n"
+ << "Compression method used: " << MethodUsed << "\n"
+ << "Compression level: " << P.level << "\n"
+ << "Binary size before compression: "
+ << formatWithCommas(UncompressedSize64) << " bytes\n"
+ << "Binary size after compression: "
+ << formatWithCommas(CompressedBuffer.size()) << " bytes\n"
+ << "Compression rate: "
+ << llvm::format("%.2lf", CompressionRate) << "\n"
+ << "Compression ratio: "
+ << llvm::format("%.2lf%%", 100.0 / CompressionRate) << "\n"
+ << "Compression speed: "
+ << llvm::format("%.2lf MB/s", CompressionSpeedMBs) << "\n"
+ << "Truncated MD5 hash: "
+ << llvm::format_hex(TruncatedHash, 16) << "\n";
+ }
+
+ return llvm::MemoryBuffer::getMemBufferCopy(
+ llvm::StringRef(FinalBuffer.data(), FinalBuffer.size()));
+}
+
+// Use packed structs to avoid padding, such that the structs map the serialized
+// format.
+LLVM_PACKED_START
+union RawCompressedBundleHeader {
+ struct CommonFields {
+ uint32_t Magic;
+ uint16_t Version;
+ uint16_t Method;
+ };
+
+ struct V1Header {
+ CommonFields Common;
+ uint32_t UncompressedFileSize;
+ uint64_t Hash;
+ };
+
+ struct V2Header {
+ CommonFields Common;
+ uint32_t FileSize;
+ uint32_t UncompressedFileSize;
+ uint64_t Hash;
+ };
+
+ struct V3Header {
+ CommonFields Common;
+ uint64_t FileSize;
+ uint64_t UncompressedFileSize;
+ uint64_t Hash;
+ };
+
+ CommonFields Common;
+ V1Header V1;
+ V2Header V2;
+ V3Header V3;
+};
+LLVM_PACKED_END
+
+// Helper method to get header size based on version
+static size_t getHeaderSize(uint16_t Version) {
+ switch (Version) {
+ case 1:
+ return sizeof(RawCompressedBundleHeader::V1Header);
+ case 2:
+ return sizeof(RawCompressedBundleHeader::V2Header);
+ case 3:
+ return sizeof(RawCompressedBundleHeader::V3Header);
+ default:
+ llvm_unreachable("Unsupported version");
+ }
+}
+
+Expected<CompressedOffloadBundle::CompressedBundleHeader>
+CompressedOffloadBundle::CompressedBundleHeader::tryParse(StringRef Blob) {
+ assert(Blob.size() >= sizeof(RawCompressedBundleHeader::CommonFields));
+ assert(llvm::identify_magic(Blob) ==
+ llvm::file_magic::offload_bundle_compressed);
+
+ RawCompressedBundleHeader Header;
+ memcpy(&Header, Blob.data(), std::min(Blob.size(), sizeof(Header)));
+
+ CompressedBundleHeader Normalized;
+ Normalized.Version = Header.Common.Version;
+
+ size_t RequiredSize = getHeaderSize(Normalized.Version);
+
+ if (Blob.size() < RequiredSize)
+ return createStringError(inconvertibleErrorCode(),
+ "Compressed bundle header size too small");
+
+ switch (Normalized.Version) {
+ case 1:
+ Normalized.UncompressedFileSize = Header.V1.UncompressedFileSize;
+ Normalized.Hash = Header.V1.Hash;
+ break;
+ case 2:
+ Normalized.FileSize = Header.V2.FileSize;
+ Normalized.UncompressedFileSize = Header.V2.UncompressedFileSize;
+ Normalized.Hash = Header.V2.Hash;
+ break;
+ case 3:
+ Normalized.FileSize = Header.V3.FileSize;
+ Normalized.UncompressedFileSize = Header.V3.UncompressedFileSize;
+ Normalized.Hash = Header.V3.Hash;
+ break;
+ default:
+ return createStringError(inconvertibleErrorCode(),
+ "Unknown compressed bundle version");
+ }
+
+ // Determine compression format
+ switch (Header.Common.Method) {
+ case static_cast<uint16_t>(compression::Format::Zlib):
+ case static_cast<uint16_t>(compression::Format::Zstd):
+ Normalized.CompressionFormat =
+ static_cast<compression::Format>(Header.Common.Method);
+ break;
+ default:
+ return createStringError(inconvertibleErrorCode(),
+ "Unknown compressing method");
+ }
+
+ return Normalized;
+}
+
+llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
+CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input,
bool Verbose) {
StringRef Blob = Input.getBuffer();
- if (Blob.size() < V1HeaderSize)
+ // Check minimum header size (using V1 as it's the smallest)
+ if (Blob.size() < sizeof(RawCompressedBundleHeader::CommonFields))
return llvm::MemoryBuffer::getMemBufferCopy(Blob);
if (llvm::identify_magic(Blob) !=
@@ -274,43 +535,20 @@ CompressedOffloadBundle::decompress(llvm::MemoryBufferRef &Input,
return llvm::MemoryBuffer::getMemBufferCopy(Blob);
}
- size_t CurrentOffset = MagicSize;
-
- uint16_t ThisVersion;
- memcpy(&ThisVersion, Blob.data() + CurrentOffset, sizeof(uint16_t));
- CurrentOffset += VersionFieldSize;
+ Expected<CompressedBundleHeader> HeaderOrErr =
+ CompressedBundleHeader::tryParse(Blob);
+ if (!HeaderOrErr)
+ return HeaderOrErr.takeError();
- uint16_t CompressionMethod;
- memcpy(&CompressionMethod, Blob.data() + CurrentOffset, sizeof(uint16_t));
- CurrentOffset += MethodFieldSize;
+ const CompressedBundleHeader &Normalized = *HeaderOrErr;
+ unsigned ThisVersion = Normalized.Version;
+ size_t HeaderSize = getHeaderSize(ThisVersion);
- uint32_t TotalFileSize;
- if (ThisVersion >= 2) {
- if (Blob.size() < V2HeaderSize)
- return createStringError(inconvertibleErrorCode(),
- "Compressed bundle header size too small");
- memcpy(&TotalFileSize, Blob.data() + CurrentOffset, sizeof(uint32_t));
- CurrentOffset += FileSizeFieldSize;
- }
+ llvm::compression::Format CompressionFormat = Normalized.CompressionFormat;
- uint32_t UncompressedSize;
- memcpy(&UncompressedSize, Blob.data() + CurrentOffset, sizeof(uint32_t));
- CurrentOffset += UncompressedSizeFieldSize;
-
- uint64_t StoredHash;
- memcpy(&StoredHash, Blob.data() + CurrentOffset, sizeof(uint64_t));
- CurrentOffset += HashFieldSize;
-
- llvm::compression::Format CompressionFormat;
- if (CompressionMethod ==
- static_cast<uint16_t>(llvm::compression::Format::Zlib))
- CompressionFormat = llvm::compression::Format::Zlib;
- else if (CompressionMethod ==
- static_cast<uint16_t>(llvm::compression::Format::Zstd))
- CompressionFormat = llvm::compression::Format::Zstd;
- else
- return createStringError(inconvertibleErrorCode(),
- "Unknown compressing method");
+ size_t TotalFileSize = Normalized.FileSize.value_or(0);
+ size_t UncompressedSize = Normalized.UncompressedFileSize;
+ auto StoredHash = Normalized.Hash;
llvm::Timer DecompressTimer("Decompression Timer", "Decompression time",
OffloadBundlerTimerGroup);
@@ -318,7 +556,9 @@ CompressedOffloadBundle::decompress(llvm::MemoryBufferRef &Input,
DecompressTimer.startTimer();
SmallVector<uint8_t, 0> DecompressedData;
- StringRef CompressedData = Blob.substr(CurrentOffset);
+ StringRef CompressedData =
+ Blob.substr(HeaderSize, TotalFileSize - HeaderSize);
+
if (llvm::Error DecompressionError = llvm::compression::decompress(
CompressionFormat, llvm::arrayRefFromStringRef(CompressedData),
DecompressedData, UncompressedSize))
@@ -332,7 +572,7 @@ CompressedOffloadBundle::decompress(llvm::MemoryBufferRef &Input,
double DecompressionTimeSeconds =
DecompressTimer.getTotalTime().getWallTime();
- // Recalculate MD5 hash for integrity check.
+ // Recalculate MD5 hash for integrity check
llvm::Timer HashRecalcTimer("Hash Recalculation Timer",
"Hash recalculation time",
OffloadBundlerTimerGroup);
@@ -378,90 +618,3 @@ CompressedOffloadBundle::decompress(llvm::MemoryBufferRef &Input,
return llvm::MemoryBuffer::getMemBufferCopy(
llvm::toStringRef(DecompressedData));
}
-
-llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
-CompressedOffloadBundle::compress(llvm::compression::Params P,
- const llvm::MemoryBuffer &Input,
- bool Verbose) {
- if (!llvm::compression::zstd::isAvailable() &&
- !llvm::compression::zlib::isAvailable())
- return createStringError(llvm::inconvertibleErrorCode(),
- "Compression not supported");
-
- llvm::Timer HashTimer("Hash Calculation Timer", "Hash calculation time",
- OffloadBundlerTimerGroup);
- if (Verbose)
- HashTimer.startTimer();
- llvm::MD5 Hash;
- llvm::MD5::MD5Result Result;
- Hash.update(Input.getBuffer());
- Hash.final(Result);
- uint64_t TruncatedHash = Result.low();
- if (Verbose)
- HashTimer.stopTimer();
-
- SmallVector<uint8_t, 0> CompressedBuffer;
- auto BufferUint8 = llvm::ArrayRef<uint8_t>(
- reinterpret_cast<const uint8_t *>(Input.getBuffer().data()),
- Input.getBuffer().size());
-
- llvm::Timer CompressTimer("Compression Timer", "Compression time",
- OffloadBundlerTimerGroup);
- if (Verbose)
- CompressTimer.startTimer();
- llvm::compression::compress(P, BufferUint8, CompressedBuffer);
- if (Verbose)
- CompressTimer.stopTimer();
-
- uint16_t CompressionMethod = static_cast<uint16_t>(P.format);
- uint32_t UncompressedSize = Input.getBuffer().size();
- uint32_t TotalFileSize = MagicNumber.size() + sizeof(TotalFileSize) +
- sizeof(Version) + sizeof(CompressionMethod) +
- sizeof(UncompressedSize) + sizeof(TruncatedHash) +
- CompressedBuffer.size();
-
- SmallVector<char, 0> FinalBuffer;
- llvm::raw_svector_ostream OS(FinalBuffer);
- OS << MagicNumber;
- OS.write(reinterpret_cast<const char *>(&Version), sizeof(Version));
- OS.write(reinterpret_cast<const char *>(&CompressionMethod),
- sizeof(CompressionMethod));
- OS.write(reinterpret_cast<const char *>(&TotalFileSize),
- sizeof(TotalFileSize));
- OS.write(reinterpret_cast<const char *>(&UncompressedSize),
- sizeof(UncompressedSize));
- OS.write(reinterpret_cast<const char *>(&TruncatedHash),
- sizeof(TruncatedHash));
- OS.write(reinterpret_cast<const char *>(CompressedBuffer.data()),
- CompressedBuffer.size());
-
- if (Verbose) {
- auto MethodUsed =
- P.format == llvm::compression::Format::Zstd ? "zstd" : "zlib";
- double CompressionRate =
- static_cast<double>(UncompressedSize) / CompressedBuffer.size();
- double CompressionTimeSeconds = CompressTimer.getTotalTime().getWallTime();
- double CompressionSpeedMBs =
- (UncompressedSize / (1024.0 * 1024.0)) / CompressionTimeSeconds;
-
- llvm::errs() << "Compressed bundle format version: " << Version << "\n"
- << "Total file size (including headers): "
- << formatWithCommas(TotalFileSize) << " bytes\n"
- << "Compression method used: " << MethodUsed << "\n"
- << "Compression level: " << P.level << "\n"
- << "Binary size before compression: "
- << formatWithCommas(UncompressedSize) << " bytes\n"
- << "Binary size after compression: "
- << formatWithCommas(CompressedBuffer.size()) << " bytes\n"
- << "Compression rate: "
- << llvm::format("%.2lf", CompressionRate) << "\n"
- << "Compression ratio: "
- << llvm::format("%.2lf%%", 100.0 / CompressionRate) << "\n"
- << "Compression speed: "
- << llvm::format("%.2lf MB/s", CompressionSpeedMBs) << "\n"
- << "Truncated MD5 hash: "
- << llvm::format_hex(TruncatedHash, 16) << "\n";
- }
- return llvm::MemoryBuffer::getMemBufferCopy(
- llvm::StringRef(FinalBuffer.data(), FinalBuffer.size()));
-}
diff --git a/llvm/tools/llvm-objdump/OffloadDump.cpp b/llvm/tools/llvm-objdump/OffloadDump.cpp
index 8a0deb35ba151..8a34d0f60a2ac 100644
--- a/llvm/tools/llvm-objdump/OffloadDump.cpp
+++ b/llvm/tools/llvm-objdump/OffloadDump.cpp
@@ -87,21 +87,30 @@ void llvm::dumpOffloadBundleFatBinary(const ObjectFile &O, StringRef ArchName) {
if (Error Err = llvm::object::extractOffloadBundleFatBinary(O, FoundBundles))
reportError(O.getFileName(), "while extracting offload FatBin bundles: " +
toString(std::move(Err)));
-
for (const auto &[BundleNum, Bundle] : llvm::enumerate(FoundBundles)) {
for (OffloadBundleEntry &Entry : Bundle.getEntries()) {
- if (!ArchName.empty() && !Entry.ID.contains(ArchName))
+ if (!ArchName.empty() && (Entry.ID.find(ArchName) != std::string::npos))
continue;
// create file name for this object file: <source-filename>.<Bundle
// Number>.<EntryID>
- std::string str = Bundle.getFileName().str() + "." + itostr(BundleNum) +
- "." + Entry.ID.str();
- if (Error Err = object::extractCodeObject(O, Entry.Offset, Entry.Size,
- StringRef(str)))
- reportError(O.getFileName(),
- "while extracting offload Bundle Entries: " +
- toString(std::move(Err)));
+ std::string str =
+ Bundle.getFileName().str() + "." + itostr(BundleNum) + "." + Entry.ID;
+
+ if (Bundle.isDecompressed()) {
+ if (Error Err = object::extractCodeObject(
+ Bundle.DecompressedBuffer->getMemBufferRef(), Entry.Offset,
+ Entry.Size, StringRef(str)))
+ reportError(O.getFileName(),
+ "while extracting offload Bundle Entries: " +
+ toString(std::move(Err)));
+ } else {
+ if (Error Err = object::extractCodeObject(O, Entry.Offset, Entry.Size,
+ StringRef(str)))
+ reportError(O.getFileName(),
+ "while extracting offload Bundle Entries: " +
+ toString(std::move(Err)));
+ }
outs() << "Extracting offload bundle: " << str << "\n";
}
}
>From 5a70f7d2fcb1297f22e0f6eeeff63de777f2a255 Mon Sep 17 00:00:00 2001
From: dsalinas_amdeng <david.salinas at amd.com>
Date: Tue, 12 Aug 2025 16:38:54 +0000
Subject: [PATCH 2/8] Clean-up from review comments.
---
llvm/include/llvm/Object/OffloadBundle.h | 3 +-
llvm/lib/Object/OffloadBundle.cpp | 145 +++++++++++------------
llvm/tools/llvm-objdump/OffloadDump.cpp | 2 +-
3 files changed, 73 insertions(+), 77 deletions(-)
diff --git a/llvm/include/llvm/Object/OffloadBundle.h b/llvm/include/llvm/Object/OffloadBundle.h
index 99f54ea4f28aa..0ee2b3bc17ea8 100644
--- a/llvm/include/llvm/Object/OffloadBundle.h
+++ b/llvm/include/llvm/Object/OffloadBundle.h
@@ -129,10 +129,9 @@ class OffloadBundleFatBin {
bool Decompress = false)
: FileName(File), Decompressed(Decompress), NumberOfEntries(0),
Entries(SmallVector<OffloadBundleEntry>()) {
- if (Decompress) {
+ if (Decompress)
DecompressedBuffer =
MemoryBuffer::getMemBufferCopy(Source.getBuffer(), File);
- }
}
};
diff --git a/llvm/lib/Object/OffloadBundle.cpp b/llvm/lib/Object/OffloadBundle.cpp
index 57a8244a9b0e5..5f86b17e2ecb1 100644
--- a/llvm/lib/Object/OffloadBundle.cpp
+++ b/llvm/lib/Object/OffloadBundle.cpp
@@ -25,7 +25,7 @@
using namespace llvm;
using namespace llvm::object;
-static llvm::TimerGroup
+static TimerGroup
OffloadBundlerTimerGroup("Offload Bundler Timer Group",
"Timer group for offload bundler");
@@ -49,16 +49,15 @@ Error extractOffloadBundle(MemoryBufferRef Contents, uint64_t SectionOffset,
if (identify_magic((*Buffer).getBuffer()) ==
file_magic::offload_bundle_compressed) {
- Magic = StringRef("CCOB");
- // decompress this bundle first.
+ Magic = "CCOB";
+ // Decompress this bundle first.
NextbundleStart = (*Buffer).getBuffer().find(Magic, Magic.size());
- if (NextbundleStart == StringRef::npos) {
+ if (NextbundleStart == StringRef::npos)
NextbundleStart = (*Buffer).getBuffer().size();
- }
ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
MemoryBuffer::getMemBuffer((*Buffer).getBuffer().take_front(
- NextbundleStart /*- Magic.size()*/),
+ NextbundleStart),
FileName, false);
if (std::error_code EC = CodeOrErr.getError())
return createFileError(FileName, EC);
@@ -68,8 +67,8 @@ Error extractOffloadBundle(MemoryBufferRef Contents, uint64_t SectionOffset,
if (!DecompressedBufferOrErr)
return createStringError(
inconvertibleErrorCode(),
- "Failed to decompress input: " +
- llvm::toString(DecompressedBufferOrErr.takeError()));
+ "failed to decompress input: " +
+ toString(DecompressedBufferOrErr.takeError()));
auto FatBundleOrErr = OffloadBundleFatBin::create(
**DecompressedBufferOrErr, Offset, FileName, true);
@@ -81,7 +80,7 @@ Error extractOffloadBundle(MemoryBufferRef Contents, uint64_t SectionOffset,
} else if (identify_magic((*Buffer).getBuffer()) ==
file_magic::offload_bundle) {
- // Create the FatBinBindle object. This will also create the Bundle Entry
+ // Create the OffloadBundleFatBin object. This will also create the Bundle Entry
// list info.
auto FatBundleOrErr = OffloadBundleFatBin::create(
*Buffer, SectionOffset + Offset, FileName);
@@ -91,7 +90,7 @@ Error extractOffloadBundle(MemoryBufferRef Contents, uint64_t SectionOffset,
// Add current Bundle to list.
Bundles.emplace_back(std::move(**FatBundleOrErr));
- Magic = StringRef("__CLANG_OFFLOAD_BUNDLE__");
+ Magic = "__CLANG_OFFLOAD_BUNDLE__";
NextbundleStart = (*Buffer).getBuffer().find(Magic, Magic.size());
}
@@ -106,7 +105,7 @@ Error OffloadBundleFatBin::readEntries(StringRef Buffer,
uint64_t SectionOffset) {
uint64_t NumOfEntries = 0;
- BinaryStreamReader Reader(Buffer, llvm::endianness::little);
+ BinaryStreamReader Reader(Buffer, endianness::little);
// Read the Magic String first.
StringRef Magic;
@@ -202,9 +201,9 @@ Error object::extractOffloadBundleFatBinary(
return Buffer.takeError();
// If it does not start with the reserved suffix, just skip this section.
- if ((llvm::identify_magic(*Buffer) == llvm::file_magic::offload_bundle) ||
- (llvm::identify_magic(*Buffer) ==
- llvm::file_magic::offload_bundle_compressed)) {
+ if ((identify_magic(*Buffer) == file_magic::offload_bundle) ||
+ (identify_magic(*Buffer) ==
+ file_magic::offload_bundle_compressed)) {
uint64_t SectionOffset = 0;
if (Obj.isELF()) {
@@ -254,10 +253,8 @@ Error object::extractCodeObject(const MemoryBufferRef Buffer, int64_t Offset,
std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr);
std::copy(Buffer.getBufferStart() + Offset,
Buffer.getBufferStart() + Offset + Size, Buf->getBufferStart());
- if (Error E = Buf->commit())
- return E;
- return Error::success();
+ return Buf->commit();
}
// given a file name, offset, and size, extract data into a code object file,
@@ -298,20 +295,20 @@ static std::string formatWithCommas(unsigned long long Value) {
return Num;
}
-llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
-CompressedOffloadBundle::compress(llvm::compression::Params P,
- const llvm::MemoryBuffer &Input,
+Expected<std::unique_ptr<MemoryBuffer>>
+CompressedOffloadBundle::compress(compression::Params P,
+ const MemoryBuffer &Input,
uint16_t Version, bool Verbose) {
- if (!llvm::compression::zstd::isAvailable() &&
- !llvm::compression::zlib::isAvailable())
- return createStringError(llvm::inconvertibleErrorCode(),
+ if (!compression::zstd::isAvailable() &&
+ !compression::zlib::isAvailable())
+ return createStringError(
"Compression not supported");
- llvm::Timer HashTimer("Hash Calculation Timer", "Hash calculation time",
+ Timer HashTimer("Hash Calculation Timer", "Hash calculation time",
OffloadBundlerTimerGroup);
if (Verbose)
HashTimer.startTimer();
- llvm::MD5 Hash;
- llvm::MD5::MD5Result Result;
+ MD5 Hash;
+ MD5::MD5Result Result;
Hash.update(Input.getBuffer());
Hash.final(Result);
uint64_t TruncatedHash = Result.low();
@@ -319,33 +316,33 @@ CompressedOffloadBundle::compress(llvm::compression::Params P,
HashTimer.stopTimer();
SmallVector<uint8_t, 0> CompressedBuffer;
- auto BufferUint8 = llvm::ArrayRef<uint8_t>(
+ auto BufferUint8 = ArrayRef<uint8_t>(
reinterpret_cast<const uint8_t *>(Input.getBuffer().data()),
Input.getBuffer().size());
- llvm::Timer CompressTimer("Compression Timer", "Compression time",
+ Timer CompressTimer("Compression Timer", "Compression time",
OffloadBundlerTimerGroup);
if (Verbose)
CompressTimer.startTimer();
- llvm::compression::compress(P, BufferUint8, CompressedBuffer);
+ compression::compress(P, BufferUint8, CompressedBuffer);
if (Verbose)
CompressTimer.stopTimer();
uint16_t CompressionMethod = static_cast<uint16_t>(P.format);
- // Store sizes in 64-bit variables first
+ // Store sizes in 64-bit variables first.
uint64_t UncompressedSize64 = Input.getBuffer().size();
uint64_t TotalFileSize64;
- // Calculate total file size based on version
+ // Calculate total file size based on version.
if (Version == 2) {
- // For V2, ensure the sizes don't exceed 32-bit limit
+ // For V2, ensure the sizes don't exceed 32-bit limit.
if (UncompressedSize64 > std::numeric_limits<uint32_t>::max())
- return createStringError(llvm::inconvertibleErrorCode(),
+ return createStringError(inconvertibleErrorCode(),
"Uncompressed size exceeds version 2 limit");
if ((MagicNumber.size() + sizeof(uint32_t) + sizeof(Version) +
sizeof(CompressionMethod) + sizeof(uint32_t) + sizeof(TruncatedHash) +
CompressedBuffer.size()) > std::numeric_limits<uint32_t>::max())
- return createStringError(llvm::inconvertibleErrorCode(),
+ return createStringError(inconvertibleErrorCode(),
"Total file size exceeds version 2 limit");
TotalFileSize64 = MagicNumber.size() + sizeof(uint32_t) + sizeof(Version) +
@@ -358,7 +355,7 @@ CompressedOffloadBundle::compress(llvm::compression::Params P,
}
SmallVector<char, 0> FinalBuffer;
- llvm::raw_svector_ostream OS(FinalBuffer);
+ raw_svector_ostream OS(FinalBuffer);
OS << MagicNumber;
OS.write(reinterpret_cast<const char *>(&Version), sizeof(Version));
OS.write(reinterpret_cast<const char *>(&CompressionMethod),
@@ -386,13 +383,13 @@ CompressedOffloadBundle::compress(llvm::compression::Params P,
if (Verbose) {
auto MethodUsed =
- P.format == llvm::compression::Format::Zstd ? "zstd" : "zlib";
+ P.format == compression::Format::Zstd ? "zstd" : "zlib";
double CompressionRate =
static_cast<double>(UncompressedSize64) / CompressedBuffer.size();
double CompressionTimeSeconds = CompressTimer.getTotalTime().getWallTime();
double CompressionSpeedMBs =
(UncompressedSize64 / (1024.0 * 1024.0)) / CompressionTimeSeconds;
- llvm::errs() << "Compressed bundle format version: " << Version << "\n"
+ errs() << "Compressed bundle format version: " << Version << "\n"
<< "Total file size (including headers): "
<< formatWithCommas(TotalFileSize64) << " bytes\n"
<< "Compression method used: " << MethodUsed << "\n"
@@ -402,17 +399,17 @@ CompressedOffloadBundle::compress(llvm::compression::Params P,
<< "Binary size after compression: "
<< formatWithCommas(CompressedBuffer.size()) << " bytes\n"
<< "Compression rate: "
- << llvm::format("%.2lf", CompressionRate) << "\n"
+ << format("%.2lf", CompressionRate) << "\n"
<< "Compression ratio: "
- << llvm::format("%.2lf%%", 100.0 / CompressionRate) << "\n"
+ << format("%.2lf%%", 100.0 / CompressionRate) << "\n"
<< "Compression speed: "
- << llvm::format("%.2lf MB/s", CompressionSpeedMBs) << "\n"
+ << format("%.2lf MB/s", CompressionSpeedMBs) << "\n"
<< "Truncated MD5 hash: "
- << llvm::format_hex(TruncatedHash, 16) << "\n";
+ << format_hex(TruncatedHash, 16) << "\n";
}
- return llvm::MemoryBuffer::getMemBufferCopy(
- llvm::StringRef(FinalBuffer.data(), FinalBuffer.size()));
+ return MemoryBuffer::getMemBufferCopy(
+ StringRef(FinalBuffer.data(), FinalBuffer.size()));
}
// Use packed structs to avoid padding, such that the structs map the serialized
@@ -452,7 +449,7 @@ union RawCompressedBundleHeader {
};
LLVM_PACKED_END
-// Helper method to get header size based on version
+// Helper method to get header size based on version.
static size_t getHeaderSize(uint16_t Version) {
switch (Version) {
case 1:
@@ -469,11 +466,11 @@ static size_t getHeaderSize(uint16_t Version) {
Expected<CompressedOffloadBundle::CompressedBundleHeader>
CompressedOffloadBundle::CompressedBundleHeader::tryParse(StringRef Blob) {
assert(Blob.size() >= sizeof(RawCompressedBundleHeader::CommonFields));
- assert(llvm::identify_magic(Blob) ==
- llvm::file_magic::offload_bundle_compressed);
+ assert(identify_magic(Blob) ==
+ file_magic::offload_bundle_compressed);
RawCompressedBundleHeader Header;
- memcpy(&Header, Blob.data(), std::min(Blob.size(), sizeof(Header)));
+ std::memcpy(&Header, Blob.data(), std::min(Blob.size(), sizeof(Header)));
CompressedBundleHeader Normalized;
Normalized.Version = Header.Common.Version;
@@ -519,20 +516,20 @@ CompressedOffloadBundle::CompressedBundleHeader::tryParse(StringRef Blob) {
return Normalized;
}
-llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
-CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input,
+Expected<std::unique_ptr<MemoryBuffer>>
+CompressedOffloadBundle::decompress(const MemoryBuffer &Input,
bool Verbose) {
StringRef Blob = Input.getBuffer();
// Check minimum header size (using V1 as it's the smallest)
if (Blob.size() < sizeof(RawCompressedBundleHeader::CommonFields))
- return llvm::MemoryBuffer::getMemBufferCopy(Blob);
+ return MemoryBuffer::getMemBufferCopy(Blob);
- if (llvm::identify_magic(Blob) !=
- llvm::file_magic::offload_bundle_compressed) {
+ if (identify_magic(Blob) !=
+ file_magic::offload_bundle_compressed) {
if (Verbose)
- llvm::errs() << "Uncompressed bundle.\n";
- return llvm::MemoryBuffer::getMemBufferCopy(Blob);
+ errs() << "Uncompressed bundle.\n";
+ return MemoryBuffer::getMemBufferCopy(Blob);
}
Expected<CompressedBundleHeader> HeaderOrErr =
@@ -544,13 +541,13 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input,
unsigned ThisVersion = Normalized.Version;
size_t HeaderSize = getHeaderSize(ThisVersion);
- llvm::compression::Format CompressionFormat = Normalized.CompressionFormat;
+ compression::Format CompressionFormat = Normalized.CompressionFormat;
size_t TotalFileSize = Normalized.FileSize.value_or(0);
size_t UncompressedSize = Normalized.UncompressedFileSize;
auto StoredHash = Normalized.Hash;
- llvm::Timer DecompressTimer("Decompression Timer", "Decompression time",
+ Timer DecompressTimer("Decompression Timer", "Decompression time",
OffloadBundlerTimerGroup);
if (Verbose)
DecompressTimer.startTimer();
@@ -559,12 +556,12 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input,
StringRef CompressedData =
Blob.substr(HeaderSize, TotalFileSize - HeaderSize);
- if (llvm::Error DecompressionError = llvm::compression::decompress(
- CompressionFormat, llvm::arrayRefFromStringRef(CompressedData),
+ if (Error DecompressionError = compression::decompress(
+ CompressionFormat, arrayRefFromStringRef(CompressedData),
DecompressedData, UncompressedSize))
return createStringError(inconvertibleErrorCode(),
"Could not decompress embedded file contents: " +
- llvm::toString(std::move(DecompressionError)));
+ toString(std::move(DecompressionError)));
if (Verbose) {
DecompressTimer.stopTimer();
@@ -573,13 +570,13 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input,
DecompressTimer.getTotalTime().getWallTime();
// Recalculate MD5 hash for integrity check
- llvm::Timer HashRecalcTimer("Hash Recalculation Timer",
+ Timer HashRecalcTimer("Hash Recalculation Timer",
"Hash recalculation time",
OffloadBundlerTimerGroup);
HashRecalcTimer.startTimer();
- llvm::MD5 Hash;
- llvm::MD5::MD5Result Result;
- Hash.update(llvm::ArrayRef<uint8_t>(DecompressedData));
+ MD5 Hash;
+ MD5::MD5Result Result;
+ Hash.update(ArrayRef<uint8_t>(DecompressedData));
Hash.final(Result);
uint64_t RecalculatedHash = Result.low();
HashRecalcTimer.stopTimer();
@@ -590,12 +587,12 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input,
double DecompressionSpeedMBs =
(UncompressedSize / (1024.0 * 1024.0)) / DecompressionTimeSeconds;
- llvm::errs() << "Compressed bundle format version: " << ThisVersion << "\n";
+ errs() << "Compressed bundle format version: " << ThisVersion << "\n";
if (ThisVersion >= 2)
- llvm::errs() << "Total file size (from header): "
+ errs() << "Total file size (from header): "
<< formatWithCommas(TotalFileSize) << " bytes\n";
- llvm::errs() << "Decompression method: "
- << (CompressionFormat == llvm::compression::Format::Zlib
+ errs() << "Decompression method: "
+ << (CompressionFormat == compression::Format::Zlib
? "zlib"
: "zstd")
<< "\n"
@@ -604,17 +601,17 @@ CompressedOffloadBundle::decompress(const llvm::MemoryBuffer &Input,
<< "Size after decompression: "
<< formatWithCommas(UncompressedSize) << " bytes\n"
<< "Compression rate: "
- << llvm::format("%.2lf", CompressionRate) << "\n"
+ << format("%.2lf", CompressionRate) << "\n"
<< "Compression ratio: "
- << llvm::format("%.2lf%%", 100.0 / CompressionRate) << "\n"
+ << format("%.2lf%%", 100.0 / CompressionRate) << "\n"
<< "Decompression speed: "
- << llvm::format("%.2lf MB/s", DecompressionSpeedMBs) << "\n"
- << "Stored hash: " << llvm::format_hex(StoredHash, 16) << "\n"
+ << format("%.2lf MB/s", DecompressionSpeedMBs) << "\n"
+ << "Stored hash: " << format_hex(StoredHash, 16) << "\n"
<< "Recalculated hash: "
- << llvm::format_hex(RecalculatedHash, 16) << "\n"
+ << format_hex(RecalculatedHash, 16) << "\n"
<< "Hashes match: " << (HashMatch ? "Yes" : "No") << "\n";
}
- return llvm::MemoryBuffer::getMemBufferCopy(
- llvm::toStringRef(DecompressedData));
+ return MemoryBuffer::getMemBufferCopy(
+ toStringRef(DecompressedData));
}
diff --git a/llvm/tools/llvm-objdump/OffloadDump.cpp b/llvm/tools/llvm-objdump/OffloadDump.cpp
index 8a34d0f60a2ac..a77537dd90eeb 100644
--- a/llvm/tools/llvm-objdump/OffloadDump.cpp
+++ b/llvm/tools/llvm-objdump/OffloadDump.cpp
@@ -89,7 +89,7 @@ void llvm::dumpOffloadBundleFatBinary(const ObjectFile &O, StringRef ArchName) {
toString(std::move(Err)));
for (const auto &[BundleNum, Bundle] : llvm::enumerate(FoundBundles)) {
for (OffloadBundleEntry &Entry : Bundle.getEntries()) {
- if (!ArchName.empty() && (Entry.ID.find(ArchName) != std::string::npos))
+ if (!ArchName.empty() && Entry.ID.find(ArchName) != std::string::npos)
continue;
// create file name for this object file: <source-filename>.<Bundle
>From bd67241c8919b8fc270e327aac84dfd01eba4164 Mon Sep 17 00:00:00 2001
From: dsalinas_amdeng <david.salinas at amd.com>
Date: Tue, 19 Aug 2025 15:51:24 +0000
Subject: [PATCH 3/8] Resolve PR comments.
---
llvm/include/llvm/Object/OffloadBundle.h | 2 +-
llvm/lib/Object/OffloadBundle.cpp | 158 ++++++++++-------------
2 files changed, 72 insertions(+), 88 deletions(-)
diff --git a/llvm/include/llvm/Object/OffloadBundle.h b/llvm/include/llvm/Object/OffloadBundle.h
index 0ee2b3bc17ea8..2ddb388c1f63d 100644
--- a/llvm/include/llvm/Object/OffloadBundle.h
+++ b/llvm/include/llvm/Object/OffloadBundle.h
@@ -59,7 +59,7 @@ class CompressedOffloadBundle {
static llvm::Expected<CompressedBundleHeader> tryParse(llvm::StringRef);
};
- static inline const uint16_t DefaultVersion = 2;
+ static inline const uint16_t DefaultVersion = 3;
static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
compress(llvm::compression::Params P, const llvm::MemoryBuffer &Input,
diff --git a/llvm/lib/Object/OffloadBundle.cpp b/llvm/lib/Object/OffloadBundle.cpp
index 5f86b17e2ecb1..3b0c063b8fd18 100644
--- a/llvm/lib/Object/OffloadBundle.cpp
+++ b/llvm/lib/Object/OffloadBundle.cpp
@@ -25,12 +25,11 @@
using namespace llvm;
using namespace llvm::object;
-static TimerGroup
- OffloadBundlerTimerGroup("Offload Bundler Timer Group",
- "Timer group for offload bundler");
+static TimerGroup OffloadBundlerTimerGroup("Offload Bundler Timer Group",
+ "Timer group for offload bundler");
// Extract an Offload bundle (usually a Offload Bundle) from a fat_bin
-// section
+// section.
Error extractOffloadBundle(MemoryBufferRef Contents, uint64_t SectionOffset,
StringRef FileName,
SmallVectorImpl<OffloadBundleFatBin> &Bundles) {
@@ -56,9 +55,9 @@ Error extractOffloadBundle(MemoryBufferRef Contents, uint64_t SectionOffset,
NextbundleStart = (*Buffer).getBuffer().size();
ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
- MemoryBuffer::getMemBuffer((*Buffer).getBuffer().take_front(
- NextbundleStart),
- FileName, false);
+ MemoryBuffer::getMemBuffer(
+ (*Buffer).getBuffer().take_front(NextbundleStart), FileName,
+ false);
if (std::error_code EC = CodeOrErr.getError())
return createFileError(FileName, EC);
@@ -80,8 +79,8 @@ Error extractOffloadBundle(MemoryBufferRef Contents, uint64_t SectionOffset,
} else if (identify_magic((*Buffer).getBuffer()) ==
file_magic::offload_bundle) {
- // Create the OffloadBundleFatBin object. This will also create the Bundle Entry
- // list info.
+ // Create the OffloadBundleFatBin object. This will also create the Bundle
+ // Entry list info.
auto FatBundleOrErr = OffloadBundleFatBin::create(
*Buffer, SectionOffset + Offset, FileName);
if (!FatBundleOrErr)
@@ -118,7 +117,7 @@ Error OffloadBundleFatBin::readEntries(StringRef Buffer,
NumberOfEntries = NumOfEntries;
- // For each Bundle Entry (code object)
+ // For each Bundle Entry (code object).
for (uint64_t I = 0; I < NumOfEntries; I++) {
uint64_t EntrySize;
uint64_t EntryOffset;
@@ -162,7 +161,7 @@ OffloadBundleFatBin::create(MemoryBufferRef Buf, uint64_t SectionOffset,
OffloadBundleFatBin *TheBundle =
new OffloadBundleFatBin(Buf, FileName, Decompress);
- // Read the Bundle Entries
+ // Read the Bundle Entries.
Error Err =
TheBundle->readEntries(Buf.getBuffer(), Decompress ? 0 : SectionOffset);
if (Err)
@@ -172,7 +171,7 @@ OffloadBundleFatBin::create(MemoryBufferRef Buf, uint64_t SectionOffset,
}
Error OffloadBundleFatBin::extractBundle(const ObjectFile &Source) {
- // This will extract all entries in the Bundle
+ // This will extract all entries in the Bundle.
for (OffloadBundleEntry &Entry : Entries) {
if (Entry.Size == 0)
@@ -202,13 +201,12 @@ Error object::extractOffloadBundleFatBinary(
// If it does not start with the reserved suffix, just skip this section.
if ((identify_magic(*Buffer) == file_magic::offload_bundle) ||
- (identify_magic(*Buffer) ==
- file_magic::offload_bundle_compressed)) {
+ (identify_magic(*Buffer) == file_magic::offload_bundle_compressed)) {
uint64_t SectionOffset = 0;
if (Obj.isELF()) {
SectionOffset = ELFSectionRef(Sec).getOffset();
- } else if (Obj.isCOFF()) // TODO: add COFF Support
+ } else if (Obj.isCOFF()) // TODO: add COFF Support.
return createStringError(object_error::parse_failed,
"COFF object files not supported.\n");
@@ -258,7 +256,7 @@ Error object::extractCodeObject(const MemoryBufferRef Buffer, int64_t Offset,
}
// given a file name, offset, and size, extract data into a code object file,
-// into file <SourceFile>-offset<Offset>-size<Size>.co
+// into file "<SourceFile>-offset<Offset>-size<Size>.co".
Error object::extractOffloadBundleByURI(StringRef URIstr) {
// create a URI object
Expected<std::unique_ptr<OffloadBundleURI>> UriOrErr(
@@ -271,7 +269,7 @@ Error object::extractOffloadBundleByURI(StringRef URIstr) {
OutputFile +=
"-offset" + itostr(Uri.Offset) + "-size" + itostr(Uri.Size) + ".co";
- // Create an ObjectFile object from uri.file_uri
+ // Create an ObjectFile object from uri.file_uri.
auto ObjOrErr = ObjectFile::createObjectFile(Uri.FileName);
if (!ObjOrErr)
return ObjOrErr.takeError();
@@ -284,7 +282,7 @@ Error object::extractOffloadBundleByURI(StringRef URIstr) {
return Error::success();
}
-// Utility function to format numbers with commas
+// Utility function to format numbers with commas.
static std::string formatWithCommas(unsigned long long Value) {
std::string Num = std::to_string(Value);
int InsertPosition = Num.length() - 3;
@@ -297,14 +295,12 @@ static std::string formatWithCommas(unsigned long long Value) {
Expected<std::unique_ptr<MemoryBuffer>>
CompressedOffloadBundle::compress(compression::Params P,
- const MemoryBuffer &Input,
- uint16_t Version, bool Verbose) {
- if (!compression::zstd::isAvailable() &&
- !compression::zlib::isAvailable())
- return createStringError(
- "Compression not supported");
+ const MemoryBuffer &Input, uint16_t Version,
+ bool Verbose) {
+ if (!compression::zstd::isAvailable() && !compression::zlib::isAvailable())
+ return createStringError("compression not supported.");
Timer HashTimer("Hash Calculation Timer", "Hash calculation time",
- OffloadBundlerTimerGroup);
+ OffloadBundlerTimerGroup);
if (Verbose)
HashTimer.startTimer();
MD5 Hash;
@@ -320,7 +316,7 @@ CompressedOffloadBundle::compress(compression::Params P,
reinterpret_cast<const uint8_t *>(Input.getBuffer().data()),
Input.getBuffer().size());
Timer CompressTimer("Compression Timer", "Compression time",
- OffloadBundlerTimerGroup);
+ OffloadBundlerTimerGroup);
if (Verbose)
CompressTimer.startTimer();
compression::compress(P, BufferUint8, CompressedBuffer);
@@ -338,17 +334,17 @@ CompressedOffloadBundle::compress(compression::Params P,
// For V2, ensure the sizes don't exceed 32-bit limit.
if (UncompressedSize64 > std::numeric_limits<uint32_t>::max())
return createStringError(inconvertibleErrorCode(),
- "Uncompressed size exceeds version 2 limit");
+ "uncompressed size exceeds version 2 limit.");
if ((MagicNumber.size() + sizeof(uint32_t) + sizeof(Version) +
sizeof(CompressionMethod) + sizeof(uint32_t) + sizeof(TruncatedHash) +
CompressedBuffer.size()) > std::numeric_limits<uint32_t>::max())
return createStringError(inconvertibleErrorCode(),
- "Total file size exceeds version 2 limit");
+ "total file size exceeds version 2 limit.");
TotalFileSize64 = MagicNumber.size() + sizeof(uint32_t) + sizeof(Version) +
sizeof(CompressionMethod) + sizeof(uint32_t) +
sizeof(TruncatedHash) + CompressedBuffer.size();
- } else { // Version 3
+ } else { // Version 3.
TotalFileSize64 = MagicNumber.size() + sizeof(uint64_t) + sizeof(Version) +
sizeof(CompressionMethod) + sizeof(uint64_t) +
sizeof(TruncatedHash) + CompressedBuffer.size();
@@ -361,7 +357,7 @@ CompressedOffloadBundle::compress(compression::Params P,
OS.write(reinterpret_cast<const char *>(&CompressionMethod),
sizeof(CompressionMethod));
- // Write size fields according to version
+ // Write size fields according to version.
if (Version == 2) {
uint32_t TotalFileSize32 = static_cast<uint32_t>(TotalFileSize64);
uint32_t UncompressedSize32 = static_cast<uint32_t>(UncompressedSize64);
@@ -369,7 +365,7 @@ CompressedOffloadBundle::compress(compression::Params P,
sizeof(TotalFileSize32));
OS.write(reinterpret_cast<const char *>(&UncompressedSize32),
sizeof(UncompressedSize32));
- } else { // Version 3
+ } else { // Version 3.
OS.write(reinterpret_cast<const char *>(&TotalFileSize64),
sizeof(TotalFileSize64));
OS.write(reinterpret_cast<const char *>(&UncompressedSize64),
@@ -382,30 +378,27 @@ CompressedOffloadBundle::compress(compression::Params P,
CompressedBuffer.size());
if (Verbose) {
- auto MethodUsed =
- P.format == compression::Format::Zstd ? "zstd" : "zlib";
+ auto MethodUsed = P.format == compression::Format::Zstd ? "zstd" : "zlib";
double CompressionRate =
static_cast<double>(UncompressedSize64) / CompressedBuffer.size();
double CompressionTimeSeconds = CompressTimer.getTotalTime().getWallTime();
double CompressionSpeedMBs =
(UncompressedSize64 / (1024.0 * 1024.0)) / CompressionTimeSeconds;
errs() << "Compressed bundle format version: " << Version << "\n"
- << "Total file size (including headers): "
- << formatWithCommas(TotalFileSize64) << " bytes\n"
- << "Compression method used: " << MethodUsed << "\n"
- << "Compression level: " << P.level << "\n"
- << "Binary size before compression: "
- << formatWithCommas(UncompressedSize64) << " bytes\n"
- << "Binary size after compression: "
- << formatWithCommas(CompressedBuffer.size()) << " bytes\n"
- << "Compression rate: "
- << format("%.2lf", CompressionRate) << "\n"
- << "Compression ratio: "
- << format("%.2lf%%", 100.0 / CompressionRate) << "\n"
- << "Compression speed: "
- << format("%.2lf MB/s", CompressionSpeedMBs) << "\n"
- << "Truncated MD5 hash: "
- << format_hex(TruncatedHash, 16) << "\n";
+ << "Total file size (including headers): "
+ << formatWithCommas(TotalFileSize64) << " bytes\n"
+ << "Compression method used: " << MethodUsed << "\n"
+ << "Compression level: " << P.level << "\n"
+ << "Binary size before compression: "
+ << formatWithCommas(UncompressedSize64) << " bytes\n"
+ << "Binary size after compression: "
+ << formatWithCommas(CompressedBuffer.size()) << " bytes\n"
+ << "Compression rate: " << format("%.2lf", CompressionRate) << "\n"
+ << "Compression ratio: "
+ << format("%.2lf%%", 100.0 / CompressionRate) << "\n"
+ << "Compression speed: " << format("%.2lf MB/s", CompressionSpeedMBs)
+ << "\n"
+ << "Truncated MD5 hash: " << format_hex(TruncatedHash, 16) << "\n";
}
return MemoryBuffer::getMemBufferCopy(
@@ -466,8 +459,7 @@ static size_t getHeaderSize(uint16_t Version) {
Expected<CompressedOffloadBundle::CompressedBundleHeader>
CompressedOffloadBundle::CompressedBundleHeader::tryParse(StringRef Blob) {
assert(Blob.size() >= sizeof(RawCompressedBundleHeader::CommonFields));
- assert(identify_magic(Blob) ==
- file_magic::offload_bundle_compressed);
+ assert(identify_magic(Blob) == file_magic::offload_bundle_compressed);
RawCompressedBundleHeader Header;
std::memcpy(&Header, Blob.data(), std::min(Blob.size(), sizeof(Header)));
@@ -479,7 +471,7 @@ CompressedOffloadBundle::CompressedBundleHeader::tryParse(StringRef Blob) {
if (Blob.size() < RequiredSize)
return createStringError(inconvertibleErrorCode(),
- "Compressed bundle header size too small");
+ "compressed bundle header size too small.");
switch (Normalized.Version) {
case 1:
@@ -498,10 +490,10 @@ CompressedOffloadBundle::CompressedBundleHeader::tryParse(StringRef Blob) {
break;
default:
return createStringError(inconvertibleErrorCode(),
- "Unknown compressed bundle version");
+ "unknown compressed bundle version.");
}
- // Determine compression format
+ // Determine compression format.
switch (Header.Common.Method) {
case static_cast<uint16_t>(compression::Format::Zlib):
case static_cast<uint16_t>(compression::Format::Zstd):
@@ -510,23 +502,21 @@ CompressedOffloadBundle::CompressedBundleHeader::tryParse(StringRef Blob) {
break;
default:
return createStringError(inconvertibleErrorCode(),
- "Unknown compressing method");
+ "unknown compressing method.");
}
return Normalized;
}
Expected<std::unique_ptr<MemoryBuffer>>
-CompressedOffloadBundle::decompress(const MemoryBuffer &Input,
- bool Verbose) {
+CompressedOffloadBundle::decompress(const MemoryBuffer &Input, bool Verbose) {
StringRef Blob = Input.getBuffer();
- // Check minimum header size (using V1 as it's the smallest)
+ // Check minimum header size (using V1 as it's the smallest).
if (Blob.size() < sizeof(RawCompressedBundleHeader::CommonFields))
return MemoryBuffer::getMemBufferCopy(Blob);
- if (identify_magic(Blob) !=
- file_magic::offload_bundle_compressed) {
+ if (identify_magic(Blob) != file_magic::offload_bundle_compressed) {
if (Verbose)
errs() << "Uncompressed bundle.\n";
return MemoryBuffer::getMemBufferCopy(Blob);
@@ -548,7 +538,7 @@ CompressedOffloadBundle::decompress(const MemoryBuffer &Input,
auto StoredHash = Normalized.Hash;
Timer DecompressTimer("Decompression Timer", "Decompression time",
- OffloadBundlerTimerGroup);
+ OffloadBundlerTimerGroup);
if (Verbose)
DecompressTimer.startTimer();
@@ -560,7 +550,7 @@ CompressedOffloadBundle::decompress(const MemoryBuffer &Input,
CompressionFormat, arrayRefFromStringRef(CompressedData),
DecompressedData, UncompressedSize))
return createStringError(inconvertibleErrorCode(),
- "Could not decompress embedded file contents: " +
+ "could not decompress embedded file contents: " +
toString(std::move(DecompressionError)));
if (Verbose) {
@@ -569,10 +559,9 @@ CompressedOffloadBundle::decompress(const MemoryBuffer &Input,
double DecompressionTimeSeconds =
DecompressTimer.getTotalTime().getWallTime();
- // Recalculate MD5 hash for integrity check
- Timer HashRecalcTimer("Hash Recalculation Timer",
- "Hash recalculation time",
- OffloadBundlerTimerGroup);
+ // Recalculate MD5 hash for integrity check.
+ Timer HashRecalcTimer("Hash Recalculation Timer", "Hash recalculation time",
+ OffloadBundlerTimerGroup);
HashRecalcTimer.startTimer();
MD5 Hash;
MD5::MD5Result Result;
@@ -590,28 +579,23 @@ CompressedOffloadBundle::decompress(const MemoryBuffer &Input,
errs() << "Compressed bundle format version: " << ThisVersion << "\n";
if (ThisVersion >= 2)
errs() << "Total file size (from header): "
- << formatWithCommas(TotalFileSize) << " bytes\n";
+ << formatWithCommas(TotalFileSize) << " bytes\n";
errs() << "Decompression method: "
- << (CompressionFormat == compression::Format::Zlib
- ? "zlib"
- : "zstd")
- << "\n"
- << "Size before decompression: "
- << formatWithCommas(CompressedData.size()) << " bytes\n"
- << "Size after decompression: "
- << formatWithCommas(UncompressedSize) << " bytes\n"
- << "Compression rate: "
- << format("%.2lf", CompressionRate) << "\n"
- << "Compression ratio: "
- << format("%.2lf%%", 100.0 / CompressionRate) << "\n"
- << "Decompression speed: "
- << format("%.2lf MB/s", DecompressionSpeedMBs) << "\n"
- << "Stored hash: " << format_hex(StoredHash, 16) << "\n"
- << "Recalculated hash: "
- << format_hex(RecalculatedHash, 16) << "\n"
- << "Hashes match: " << (HashMatch ? "Yes" : "No") << "\n";
+ << (CompressionFormat == compression::Format::Zlib ? "zlib" : "zstd")
+ << "\n"
+ << "Size before decompression: "
+ << formatWithCommas(CompressedData.size()) << " bytes\n"
+ << "Size after decompression: " << formatWithCommas(UncompressedSize)
+ << " bytes\n"
+ << "Compression rate: " << format("%.2lf", CompressionRate) << "\n"
+ << "Compression ratio: "
+ << format("%.2lf%%", 100.0 / CompressionRate) << "\n"
+ << "Decompression speed: "
+ << format("%.2lf MB/s", DecompressionSpeedMBs) << "\n"
+ << "Stored hash: " << format_hex(StoredHash, 16) << "\n"
+ << "Recalculated hash: " << format_hex(RecalculatedHash, 16) << "\n"
+ << "Hashes match: " << (HashMatch ? "Yes" : "No") << "\n";
}
- return MemoryBuffer::getMemBufferCopy(
- toStringRef(DecompressedData));
+ return MemoryBuffer::getMemBufferCopy(toStringRef(DecompressedData));
}
>From 98f59d41d0ac3bee691c9bf0d64b825468f10a4b Mon Sep 17 00:00:00 2001
From: david-salinas <dsalinas at amd.com>
Date: Thu, 28 Aug 2025 19:53:07 +0000
Subject: [PATCH 4/8] Resolve PR comments part 2
---
llvm/lib/Object/OffloadBundle.cpp | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/llvm/lib/Object/OffloadBundle.cpp b/llvm/lib/Object/OffloadBundle.cpp
index 3b0c063b8fd18..bf7dc267de207 100644
--- a/llvm/lib/Object/OffloadBundle.cpp
+++ b/llvm/lib/Object/OffloadBundle.cpp
@@ -104,7 +104,7 @@ Error OffloadBundleFatBin::readEntries(StringRef Buffer,
uint64_t SectionOffset) {
uint64_t NumOfEntries = 0;
- BinaryStreamReader Reader(Buffer, endianness::little);
+ BinaryStreamReader Reader(Buffer, llvm::endianness::little);
// Read the Magic String first.
StringRef Magic;
@@ -200,15 +200,16 @@ Error object::extractOffloadBundleFatBinary(
return Buffer.takeError();
// If it does not start with the reserved suffix, just skip this section.
- if ((identify_magic(*Buffer) == file_magic::offload_bundle) ||
- (identify_magic(*Buffer) == file_magic::offload_bundle_compressed)) {
+ if ((llvm::identify_magic(*Buffer) == file_magic::offload_bundle) ||
+ (llvm::identify_magic(*Buffer) ==
+ file_magic::offload_bundle_compressed)) {
uint64_t SectionOffset = 0;
if (Obj.isELF()) {
SectionOffset = ELFSectionRef(Sec).getOffset();
} else if (Obj.isCOFF()) // TODO: add COFF Support.
return createStringError(object_error::parse_failed,
- "COFF object files not supported.\n");
+ "COFF object files not supported");
MemoryBufferRef Contents(*Buffer, Obj.getFileName());
if (Error Err = extractOffloadBundle(Contents, SectionOffset,
@@ -334,12 +335,12 @@ CompressedOffloadBundle::compress(compression::Params P,
// For V2, ensure the sizes don't exceed 32-bit limit.
if (UncompressedSize64 > std::numeric_limits<uint32_t>::max())
return createStringError(inconvertibleErrorCode(),
- "uncompressed size exceeds version 2 limit.");
+ "uncompressed size exceeds version 2 limit");
if ((MagicNumber.size() + sizeof(uint32_t) + sizeof(Version) +
sizeof(CompressionMethod) + sizeof(uint32_t) + sizeof(TruncatedHash) +
CompressedBuffer.size()) > std::numeric_limits<uint32_t>::max())
return createStringError(inconvertibleErrorCode(),
- "total file size exceeds version 2 limit.");
+ "total file size exceeds version 2 limit");
TotalFileSize64 = MagicNumber.size() + sizeof(uint32_t) + sizeof(Version) +
sizeof(CompressionMethod) + sizeof(uint32_t) +
@@ -471,7 +472,7 @@ CompressedOffloadBundle::CompressedBundleHeader::tryParse(StringRef Blob) {
if (Blob.size() < RequiredSize)
return createStringError(inconvertibleErrorCode(),
- "compressed bundle header size too small.");
+ "compressed bundle header size too small");
switch (Normalized.Version) {
case 1:
@@ -490,7 +491,7 @@ CompressedOffloadBundle::CompressedBundleHeader::tryParse(StringRef Blob) {
break;
default:
return createStringError(inconvertibleErrorCode(),
- "unknown compressed bundle version.");
+ "unknown compressed bundle version");
}
// Determine compression format.
@@ -502,7 +503,7 @@ CompressedOffloadBundle::CompressedBundleHeader::tryParse(StringRef Blob) {
break;
default:
return createStringError(inconvertibleErrorCode(),
- "unknown compressing method.");
+ "unknown compressing method");
}
return Normalized;
@@ -518,7 +519,7 @@ CompressedOffloadBundle::decompress(const MemoryBuffer &Input, bool Verbose) {
if (identify_magic(Blob) != file_magic::offload_bundle_compressed) {
if (Verbose)
- errs() << "Uncompressed bundle.\n";
+ errs() << "Uncompressed bundle\n";
return MemoryBuffer::getMemBufferCopy(Blob);
}
>From d3c9a79428d724e51566aa8ba069191298e62ecd Mon Sep 17 00:00:00 2001
From: david-salinas <dsalinas at amd.com>
Date: Thu, 4 Sep 2025 20:37:09 +0000
Subject: [PATCH 5/8] Change Offloading API to require a output stream to be
passed for decompress/compress.
Default the output stream to errs().
---
llvm/include/llvm/Object/OffloadBundle.h | 4 ++--
llvm/lib/Object/OffloadBundle.cpp | 16 ++++++++--------
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/llvm/include/llvm/Object/OffloadBundle.h b/llvm/include/llvm/Object/OffloadBundle.h
index 2ddb388c1f63d..442530b2d4af4 100644
--- a/llvm/include/llvm/Object/OffloadBundle.h
+++ b/llvm/include/llvm/Object/OffloadBundle.h
@@ -63,9 +63,9 @@ class CompressedOffloadBundle {
static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
compress(llvm::compression::Params P, const llvm::MemoryBuffer &Input,
- uint16_t Version, bool Verbose = false);
+ uint16_t Version, bool Verbose = false, raw_ostream &OutS = errs());
static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
- decompress(const llvm::MemoryBuffer &Input, bool Verbose = false);
+ decompress(const llvm::MemoryBuffer &Input, bool Verbose = false, raw_ostream &OS = errs());
};
/// Bundle entry in binary clang-offload-bundler format.
diff --git a/llvm/lib/Object/OffloadBundle.cpp b/llvm/lib/Object/OffloadBundle.cpp
index bf7dc267de207..072dc36227ab3 100644
--- a/llvm/lib/Object/OffloadBundle.cpp
+++ b/llvm/lib/Object/OffloadBundle.cpp
@@ -62,7 +62,7 @@ Error extractOffloadBundle(MemoryBufferRef Contents, uint64_t SectionOffset,
return createFileError(FileName, EC);
Expected<std::unique_ptr<MemoryBuffer>> DecompressedBufferOrErr =
- CompressedOffloadBundle::decompress(**CodeOrErr, false);
+ CompressedOffloadBundle::decompress(**CodeOrErr, false, errs());
if (!DecompressedBufferOrErr)
return createStringError(
inconvertibleErrorCode(),
@@ -297,7 +297,7 @@ static std::string formatWithCommas(unsigned long long Value) {
Expected<std::unique_ptr<MemoryBuffer>>
CompressedOffloadBundle::compress(compression::Params P,
const MemoryBuffer &Input, uint16_t Version,
- bool Verbose) {
+ bool Verbose, raw_ostream &OutS) {
if (!compression::zstd::isAvailable() && !compression::zlib::isAvailable())
return createStringError("compression not supported.");
Timer HashTimer("Hash Calculation Timer", "Hash calculation time",
@@ -385,7 +385,7 @@ CompressedOffloadBundle::compress(compression::Params P,
double CompressionTimeSeconds = CompressTimer.getTotalTime().getWallTime();
double CompressionSpeedMBs =
(UncompressedSize64 / (1024.0 * 1024.0)) / CompressionTimeSeconds;
- errs() << "Compressed bundle format version: " << Version << "\n"
+ OutS << "Compressed bundle format version: " << Version << "\n"
<< "Total file size (including headers): "
<< formatWithCommas(TotalFileSize64) << " bytes\n"
<< "Compression method used: " << MethodUsed << "\n"
@@ -510,7 +510,7 @@ CompressedOffloadBundle::CompressedBundleHeader::tryParse(StringRef Blob) {
}
Expected<std::unique_ptr<MemoryBuffer>>
-CompressedOffloadBundle::decompress(const MemoryBuffer &Input, bool Verbose) {
+CompressedOffloadBundle::decompress(const MemoryBuffer &Input, bool Verbose, raw_ostream &OS) {
StringRef Blob = Input.getBuffer();
// Check minimum header size (using V1 as it's the smallest).
@@ -519,7 +519,7 @@ CompressedOffloadBundle::decompress(const MemoryBuffer &Input, bool Verbose) {
if (identify_magic(Blob) != file_magic::offload_bundle_compressed) {
if (Verbose)
- errs() << "Uncompressed bundle\n";
+ OS << "Uncompressed bundle\n";
return MemoryBuffer::getMemBufferCopy(Blob);
}
@@ -577,11 +577,11 @@ CompressedOffloadBundle::decompress(const MemoryBuffer &Input, bool Verbose) {
double DecompressionSpeedMBs =
(UncompressedSize / (1024.0 * 1024.0)) / DecompressionTimeSeconds;
- errs() << "Compressed bundle format version: " << ThisVersion << "\n";
+ OS << "Compressed bundle format version: " << ThisVersion << "\n";
if (ThisVersion >= 2)
- errs() << "Total file size (from header): "
+ OS << "Total file size (from header): "
<< formatWithCommas(TotalFileSize) << " bytes\n";
- errs() << "Decompression method: "
+ OS << "Decompression method: "
<< (CompressionFormat == compression::Format::Zlib ? "zlib" : "zstd")
<< "\n"
<< "Size before decompression: "
>From de45503267dff3b5cfffabe7431ecb776a520b9a Mon Sep 17 00:00:00 2001
From: david-salinas <dsalinas at amd.com>
Date: Wed, 10 Sep 2025 16:11:28 +0000
Subject: [PATCH 6/8] Refactor API change for user specified output stream
---
llvm/include/llvm/Object/OffloadBundle.h | 5 +-
llvm/lib/Object/OffloadBundle.cpp | 95 +++++++++++++-----------
2 files changed, 53 insertions(+), 47 deletions(-)
diff --git a/llvm/include/llvm/Object/OffloadBundle.h b/llvm/include/llvm/Object/OffloadBundle.h
index 442530b2d4af4..1cfa92ed2b38f 100644
--- a/llvm/include/llvm/Object/OffloadBundle.h
+++ b/llvm/include/llvm/Object/OffloadBundle.h
@@ -63,9 +63,10 @@ class CompressedOffloadBundle {
static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
compress(llvm::compression::Params P, const llvm::MemoryBuffer &Input,
- uint16_t Version, bool Verbose = false, raw_ostream &OutS = errs());
+ uint16_t Version, raw_ostream *VerboseStream = nullptr);
static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
- decompress(const llvm::MemoryBuffer &Input, bool Verbose = false, raw_ostream &OS = errs());
+ decompress(const llvm::MemoryBuffer &Input,
+ raw_ostream *VerboseStream = nullptr);
};
/// Bundle entry in binary clang-offload-bundler format.
diff --git a/llvm/lib/Object/OffloadBundle.cpp b/llvm/lib/Object/OffloadBundle.cpp
index 072dc36227ab3..8d9f42e5da3c6 100644
--- a/llvm/lib/Object/OffloadBundle.cpp
+++ b/llvm/lib/Object/OffloadBundle.cpp
@@ -62,7 +62,7 @@ Error extractOffloadBundle(MemoryBufferRef Contents, uint64_t SectionOffset,
return createFileError(FileName, EC);
Expected<std::unique_ptr<MemoryBuffer>> DecompressedBufferOrErr =
- CompressedOffloadBundle::decompress(**CodeOrErr, false, errs());
+ CompressedOffloadBundle::decompress(**CodeOrErr, &nulls());
if (!DecompressedBufferOrErr)
return createStringError(
inconvertibleErrorCode(),
@@ -297,19 +297,19 @@ static std::string formatWithCommas(unsigned long long Value) {
Expected<std::unique_ptr<MemoryBuffer>>
CompressedOffloadBundle::compress(compression::Params P,
const MemoryBuffer &Input, uint16_t Version,
- bool Verbose, raw_ostream &OutS) {
+ raw_ostream *VerboseStream) {
if (!compression::zstd::isAvailable() && !compression::zlib::isAvailable())
return createStringError("compression not supported.");
Timer HashTimer("Hash Calculation Timer", "Hash calculation time",
OffloadBundlerTimerGroup);
- if (Verbose)
+ if (VerboseStream)
HashTimer.startTimer();
MD5 Hash;
MD5::MD5Result Result;
Hash.update(Input.getBuffer());
Hash.final(Result);
uint64_t TruncatedHash = Result.low();
- if (Verbose)
+ if (VerboseStream)
HashTimer.stopTimer();
SmallVector<uint8_t, 0> CompressedBuffer;
@@ -318,10 +318,10 @@ CompressedOffloadBundle::compress(compression::Params P,
Input.getBuffer().size());
Timer CompressTimer("Compression Timer", "Compression time",
OffloadBundlerTimerGroup);
- if (Verbose)
+ if (VerboseStream)
CompressTimer.startTimer();
compression::compress(P, BufferUint8, CompressedBuffer);
- if (Verbose)
+ if (VerboseStream)
CompressTimer.stopTimer();
uint16_t CompressionMethod = static_cast<uint16_t>(P.format);
@@ -378,28 +378,30 @@ CompressedOffloadBundle::compress(compression::Params P,
OS.write(reinterpret_cast<const char *>(CompressedBuffer.data()),
CompressedBuffer.size());
- if (Verbose) {
+ if (VerboseStream) {
auto MethodUsed = P.format == compression::Format::Zstd ? "zstd" : "zlib";
double CompressionRate =
static_cast<double>(UncompressedSize64) / CompressedBuffer.size();
double CompressionTimeSeconds = CompressTimer.getTotalTime().getWallTime();
double CompressionSpeedMBs =
(UncompressedSize64 / (1024.0 * 1024.0)) / CompressionTimeSeconds;
- OutS << "Compressed bundle format version: " << Version << "\n"
- << "Total file size (including headers): "
- << formatWithCommas(TotalFileSize64) << " bytes\n"
- << "Compression method used: " << MethodUsed << "\n"
- << "Compression level: " << P.level << "\n"
- << "Binary size before compression: "
- << formatWithCommas(UncompressedSize64) << " bytes\n"
- << "Binary size after compression: "
- << formatWithCommas(CompressedBuffer.size()) << " bytes\n"
- << "Compression rate: " << format("%.2lf", CompressionRate) << "\n"
- << "Compression ratio: "
- << format("%.2lf%%", 100.0 / CompressionRate) << "\n"
- << "Compression speed: " << format("%.2lf MB/s", CompressionSpeedMBs)
- << "\n"
- << "Truncated MD5 hash: " << format_hex(TruncatedHash, 16) << "\n";
+ *VerboseStream << "Compressed bundle format version: " << Version << "\n"
+ << "Total file size (including headers): "
+ << formatWithCommas(TotalFileSize64) << " bytes\n"
+ << "Compression method used: " << MethodUsed << "\n"
+ << "Compression level: " << P.level << "\n"
+ << "Binary size before compression: "
+ << formatWithCommas(UncompressedSize64) << " bytes\n"
+ << "Binary size after compression: "
+ << formatWithCommas(CompressedBuffer.size()) << " bytes\n"
+ << "Compression rate: " << format("%.2lf", CompressionRate)
+ << "\n"
+ << "Compression ratio: "
+ << format("%.2lf%%", 100.0 / CompressionRate) << "\n"
+ << "Compression speed: "
+ << format("%.2lf MB/s", CompressionSpeedMBs) << "\n"
+ << "Truncated MD5 hash: " << format_hex(TruncatedHash, 16)
+ << "\n";
}
return MemoryBuffer::getMemBufferCopy(
@@ -510,7 +512,8 @@ CompressedOffloadBundle::CompressedBundleHeader::tryParse(StringRef Blob) {
}
Expected<std::unique_ptr<MemoryBuffer>>
-CompressedOffloadBundle::decompress(const MemoryBuffer &Input, bool Verbose, raw_ostream &OS) {
+CompressedOffloadBundle::decompress(const MemoryBuffer &Input,
+ raw_ostream *VerboseStream) {
StringRef Blob = Input.getBuffer();
// Check minimum header size (using V1 as it's the smallest).
@@ -518,8 +521,8 @@ CompressedOffloadBundle::decompress(const MemoryBuffer &Input, bool Verbose, raw
return MemoryBuffer::getMemBufferCopy(Blob);
if (identify_magic(Blob) != file_magic::offload_bundle_compressed) {
- if (Verbose)
- OS << "Uncompressed bundle\n";
+ if (VerboseStream)
+ *VerboseStream << "Uncompressed bundle\n";
return MemoryBuffer::getMemBufferCopy(Blob);
}
@@ -540,7 +543,7 @@ CompressedOffloadBundle::decompress(const MemoryBuffer &Input, bool Verbose, raw
Timer DecompressTimer("Decompression Timer", "Decompression time",
OffloadBundlerTimerGroup);
- if (Verbose)
+ if (VerboseStream)
DecompressTimer.startTimer();
SmallVector<uint8_t, 0> DecompressedData;
@@ -554,7 +557,7 @@ CompressedOffloadBundle::decompress(const MemoryBuffer &Input, bool Verbose, raw
"could not decompress embedded file contents: " +
toString(std::move(DecompressionError)));
- if (Verbose) {
+ if (VerboseStream) {
DecompressTimer.stopTimer();
double DecompressionTimeSeconds =
@@ -577,25 +580,27 @@ CompressedOffloadBundle::decompress(const MemoryBuffer &Input, bool Verbose, raw
double DecompressionSpeedMBs =
(UncompressedSize / (1024.0 * 1024.0)) / DecompressionTimeSeconds;
- OS << "Compressed bundle format version: " << ThisVersion << "\n";
+ *VerboseStream << "Compressed bundle format version: " << ThisVersion
+ << "\n";
if (ThisVersion >= 2)
- OS << "Total file size (from header): "
- << formatWithCommas(TotalFileSize) << " bytes\n";
- OS << "Decompression method: "
- << (CompressionFormat == compression::Format::Zlib ? "zlib" : "zstd")
- << "\n"
- << "Size before decompression: "
- << formatWithCommas(CompressedData.size()) << " bytes\n"
- << "Size after decompression: " << formatWithCommas(UncompressedSize)
- << " bytes\n"
- << "Compression rate: " << format("%.2lf", CompressionRate) << "\n"
- << "Compression ratio: "
- << format("%.2lf%%", 100.0 / CompressionRate) << "\n"
- << "Decompression speed: "
- << format("%.2lf MB/s", DecompressionSpeedMBs) << "\n"
- << "Stored hash: " << format_hex(StoredHash, 16) << "\n"
- << "Recalculated hash: " << format_hex(RecalculatedHash, 16) << "\n"
- << "Hashes match: " << (HashMatch ? "Yes" : "No") << "\n";
+ *VerboseStream << "Total file size (from header): "
+ << formatWithCommas(TotalFileSize) << " bytes\n";
+ *VerboseStream
+ << "Decompression method: "
+ << (CompressionFormat == compression::Format::Zlib ? "zlib" : "zstd")
+ << "\n"
+ << "Size before decompression: "
+ << formatWithCommas(CompressedData.size()) << " bytes\n"
+ << "Size after decompression: " << formatWithCommas(UncompressedSize)
+ << " bytes\n"
+ << "Compression rate: " << format("%.2lf", CompressionRate) << "\n"
+ << "Compression ratio: " << format("%.2lf%%", 100.0 / CompressionRate)
+ << "\n"
+ << "Decompression speed: "
+ << format("%.2lf MB/s", DecompressionSpeedMBs) << "\n"
+ << "Stored hash: " << format_hex(StoredHash, 16) << "\n"
+ << "Recalculated hash: " << format_hex(RecalculatedHash, 16) << "\n"
+ << "Hashes match: " << (HashMatch ? "Yes" : "No") << "\n";
}
return MemoryBuffer::getMemBufferCopy(toStringRef(DecompressedData));
>From 589e8980a93719c319a3ab271ce2142f274f7743 Mon Sep 17 00:00:00 2001
From: david-salinas <dsalinas at amd.com>
Date: Mon, 15 Sep 2025 18:11:53 +0000
Subject: [PATCH 7/8] Resolve build issue and address PR comments.
---
llvm/include/llvm/Object/OffloadBundle.h | 11 ++++-------
llvm/lib/Object/OffloadBundle.cpp | 5 ++---
2 files changed, 6 insertions(+), 10 deletions(-)
diff --git a/llvm/include/llvm/Object/OffloadBundle.h b/llvm/include/llvm/Object/OffloadBundle.h
index 1cfa92ed2b38f..7217ec669467e 100644
--- a/llvm/include/llvm/Object/OffloadBundle.h
+++ b/llvm/include/llvm/Object/OffloadBundle.h
@@ -75,11 +75,8 @@ struct OffloadBundleEntry {
uint64_t Size = 0u;
uint64_t IDLength = 0u;
std::string ID;
- OffloadBundleEntry(uint64_t O, uint64_t S, uint64_t I, std::string T)
- : Offset(O), Size(S), IDLength(I) {
- ID.reserve(T.size());
- ID = T;
- }
+ OffloadBundleEntry(uint64_t O, uint64_t S, uint64_t I, StringRef T)
+ : Offset(O), Size(S), IDLength(I), ID(T.str()) {}
void dumpInfo(raw_ostream &OS) {
OS << "Offset = " << Offset << ", Size = " << Size
<< ", ID Length = " << IDLength << ", ID = " << ID << "\n";
@@ -96,8 +93,8 @@ class OffloadBundleFatBin {
uint64_t Size = 0u;
StringRef FileName;
uint64_t NumberOfEntries;
- SmallVector<OffloadBundleEntry> Entries;
bool Decompressed;
+ SmallVector<OffloadBundleEntry> Entries;
public:
std::unique_ptr<MemoryBuffer> DecompressedBuffer;
@@ -128,7 +125,7 @@ class OffloadBundleFatBin {
OffloadBundleFatBin(MemoryBufferRef Source, StringRef File,
bool Decompress = false)
- : FileName(File), Decompressed(Decompress), NumberOfEntries(0),
+ : FileName(File), NumberOfEntries(0), Decompressed(Decompress),
Entries(SmallVector<OffloadBundleEntry>()) {
if (Decompress)
DecompressedBuffer =
diff --git a/llvm/lib/Object/OffloadBundle.cpp b/llvm/lib/Object/OffloadBundle.cpp
index 8d9f42e5da3c6..1c45dd233a56c 100644
--- a/llvm/lib/Object/OffloadBundle.cpp
+++ b/llvm/lib/Object/OffloadBundle.cpp
@@ -62,7 +62,7 @@ Error extractOffloadBundle(MemoryBufferRef Contents, uint64_t SectionOffset,
return createFileError(FileName, EC);
Expected<std::unique_ptr<MemoryBuffer>> DecompressedBufferOrErr =
- CompressedOffloadBundle::decompress(**CodeOrErr, &nulls());
+ CompressedOffloadBundle::decompress(**CodeOrErr, nullptr);
if (!DecompressedBufferOrErr)
return createStringError(
inconvertibleErrorCode(),
@@ -137,8 +137,7 @@ Error OffloadBundleFatBin::readEntries(StringRef Buffer,
return errorCodeToError(object_error::parse_failed);
auto Entry = std::make_unique<OffloadBundleEntry>(
- EntryOffset + SectionOffset, EntrySize, EntryIDSize,
- std::move(EntryID.str()));
+ EntryOffset + SectionOffset, EntrySize, EntryIDSize, EntryID);
Entries.push_back(*Entry);
}
>From 7ce94fe5b6300d41b2fd612c0324688d1fb811e5 Mon Sep 17 00:00:00 2001
From: david-salinas <dsalinas at amd.com>
Date: Thu, 18 Sep 2025 19:56:26 +0000
Subject: [PATCH 8/8] Address PR comment.
---
llvm/lib/Object/OffloadBundle.cpp | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Object/OffloadBundle.cpp b/llvm/lib/Object/OffloadBundle.cpp
index 1c45dd233a56c..040ecc0a41619 100644
--- a/llvm/lib/Object/OffloadBundle.cpp
+++ b/llvm/lib/Object/OffloadBundle.cpp
@@ -333,13 +333,15 @@ CompressedOffloadBundle::compress(compression::Params P,
if (Version == 2) {
// For V2, ensure the sizes don't exceed 32-bit limit.
if (UncompressedSize64 > std::numeric_limits<uint32_t>::max())
- return createStringError(inconvertibleErrorCode(),
- "uncompressed size exceeds version 2 limit");
+ return createStringError(
+ inconvertibleErrorCode(),
+ "uncompressed size exceeds version 2 unsigned 32-bit integer limit");
if ((MagicNumber.size() + sizeof(uint32_t) + sizeof(Version) +
sizeof(CompressionMethod) + sizeof(uint32_t) + sizeof(TruncatedHash) +
CompressedBuffer.size()) > std::numeric_limits<uint32_t>::max())
- return createStringError(inconvertibleErrorCode(),
- "total file size exceeds version 2 limit");
+ return createStringError(
+ inconvertibleErrorCode(),
+ "total file size exceeds version 2 unsigned 32-bit integer limit");
TotalFileSize64 = MagicNumber.size() + sizeof(uint32_t) + sizeof(Version) +
sizeof(CompressionMethod) + sizeof(uint32_t) +
More information about the llvm-commits
mailing list