[llvm] [llvm-objdump] Add support for HIP offload bundles (PR #114834)
Joseph Huber via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 25 18:40:46 PST 2025
================
@@ -0,0 +1,212 @@
+//===--- OffloadBundle.h - Utilities for handling offloading code -*- C++
+//-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the binary format used for budingling device metadata with
+// an associated device image. The data can then be stored inside a host object
+// file to create a fat binary and read by the linker. This is intended to be a
+// thin wrapper around the image itself. If this format becomes sufficiently
+// complex it should be moved to a standard binary format like msgpack or ELF.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_OFFLOADBUNDLE_H
+#define LLVM_OBJECT_OFFLOADBUNDLE_H
+
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Object/Binary.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/Compression.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <memory>
+
+namespace llvm {
+
+namespace object {
+
+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:
+ static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
+ compress(llvm::compression::Params P, const llvm::MemoryBuffer &Input,
+ bool Verbose = false);
+ static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
+ decompress(llvm::MemoryBufferRef &Input, bool Verbose = false);
+};
+
+/// Bundle entry in binary clang-offload-bundler format.
+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) {}
+ void dumpInfo(raw_ostream &OS) {
+ OS << "Offset = " << Offset << ", Size = " << Size
+ << ", ID Length = " << IDLength << ", ID = " << ID;
+ }
+ void dumpURI(raw_ostream &OS, StringRef FilePath) {
+ OS << ID.data() << "\tfile://" << FilePath << "#offset=" << Offset
+ << "&size=" << Size << "\n";
+ }
+};
+
+/// Fat binary embedded in object files in clang-offload-bundler format
+class OffloadBundleFatBin {
+
+ uint64_t Size = 0u;
+ StringRef FileName;
+ uint64_t NumberOfEntries;
+ SmallVector<OffloadBundleEntry> Entries;
+
+public:
+ SmallVector<OffloadBundleEntry> getEntries() { return Entries; }
+ uint64_t getSize() const { return Size; }
+ StringRef getFileName() const { return FileName; }
+ uint64_t getNumEntries() const { return NumberOfEntries; }
+
+ static Expected<std::unique_ptr<OffloadBundleFatBin>>
+ create(MemoryBufferRef, uint64_t SectionOffset, StringRef FileName);
+ Error extractBundle(const ObjectFile &Source);
+
+ Error dumpEntryToCodeObject();
+
+ Error readEntries(StringRef Section, uint64_t SectionOffset);
+ void dumpEntries() {
+ for (OffloadBundleEntry &Entry : Entries)
+ Entry.dumpInfo(outs());
+ }
+
+ void printEntriesAsURI() {
+ for (OffloadBundleEntry &Entry : Entries)
+ Entry.dumpURI(outs(), FileName);
+ }
+
+ OffloadBundleFatBin(MemoryBufferRef Source, StringRef File)
+ : FileName(File), NumberOfEntries(0),
+ Entries(SmallVector<OffloadBundleEntry>()) {}
+
+ SmallVector<OffloadBundleEntry> entryIDContains(StringRef Str) {
+
+ SmallVector<OffloadBundleEntry> Found = SmallVector<OffloadBundleEntry>();
+ llvm::transform(Entries, std::back_inserter(Found), [Str](auto &X) {
+ if (X.ID.contains(Str))
+ return X;
+ });
+ return Found;
+ }
+};
+
+enum UriTypeT { FILE_URI, MEMORY_URI };
+
+struct OffloadBundleURI {
+ int64_t Offset = 0;
+ int64_t Size = 0;
+ uint64_t ProcessID = 0;
+ StringRef FileName;
+ UriTypeT URIType;
+
+ // Constructors
+ // TODO: add a Copy ctor ?
+ OffloadBundleURI(StringRef File, int64_t Off, int64_t Size)
+ : Offset(Off), Size(Size), ProcessID(0), FileName(File),
+ URIType(FILE_URI) {}
+
+public:
+ static Expected<std::unique_ptr<OffloadBundleURI>>
+ createOffloadBundleURI(StringRef Str, UriTypeT Type) {
+ switch (Type) {
+ case FILE_URI:
+ return createFileURI(Str);
+ break;
+ case MEMORY_URI:
+ return createMemoryURI(Str);
+ break;
+ default:
+ return createStringError(object_error::parse_failed,
+ "Unrecognized URI type");
+ }
+ }
+
+ static Expected<std::unique_ptr<OffloadBundleURI>>
+ createFileURI(StringRef Str) {
+ int64_t O = 0;
+ int64_t S = 0;
+
+ if (Str.consume_front("file://")) {
----------------
jhuber6 wrote:
Not a fan of the nesting here, can we do instead `if (!Str.consume_front) error`?
https://github.com/llvm/llvm-project/pull/114834
More information about the llvm-commits
mailing list