Files
gps/tools/local/circt/include/llvm/Object/OffloadBundle.h
T
2026-07-12 11:01:51 +03:00

228 lines
7.6 KiB
C++

//===- OffloadBundle.h - Utilities for offload bundles---*- 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/Compiler.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"
#include <memory>
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 llvm::StringRef MagicNumber = "CCOB";
public:
struct CompressedBundleHeader {
unsigned Version;
llvm::compression::Format CompressionFormat;
std::optional<size_t> FileSize;
size_t UncompressedFileSize;
uint64_t Hash;
LLVM_ABI static llvm::Expected<CompressedBundleHeader>
tryParse(llvm::StringRef);
};
static inline const uint16_t DefaultVersion = 3;
LLVM_ABI static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
compress(llvm::compression::Params P, const llvm::MemoryBuffer &Input,
uint16_t Version, raw_ostream *VerboseStream = nullptr);
LLVM_ABI static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
decompress(const llvm::MemoryBuffer &Input,
raw_ostream *VerboseStream = nullptr);
};
/// Bundle entry in binary clang-offload-bundler format.
struct OffloadBundleEntry {
uint64_t Offset = 0u;
uint64_t Size = 0u;
uint64_t IDLength = 0u;
std::string ID;
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";
}
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;
bool Decompressed;
SmallVector<OffloadBundleEntry> Entries;
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,
bool Decompress = false);
LLVM_ABI Error extractBundle(const ObjectFile &Source);
LLVM_ABI Error dumpEntryToCodeObject();
LLVM_ABI 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,
bool Decompress = false)
: FileName(File), NumberOfEntries(0), Decompressed(Decompress),
Entries(SmallVector<OffloadBundleEntry>()) {
if (Decompress)
DecompressedBuffer =
MemoryBuffer::getMemBufferCopy(Source.getBuffer(), File);
}
};
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;
}
llvm_unreachable("Unknown UriTypeT enum");
}
static Expected<std::unique_ptr<OffloadBundleURI>>
createFileURI(StringRef Str) {
int64_t O = 0;
int64_t S = 0;
if (!Str.consume_front("file://"))
return createStringError(object_error::parse_failed,
"Reading type of URI");
StringRef FilePathname =
Str.take_until([](char C) { return (C == '#') || (C == '?'); });
Str = Str.drop_front(FilePathname.size());
if (!Str.consume_front("#offset="))
return createStringError(object_error::parse_failed,
"Reading 'offset' in URI");
StringRef OffsetStr = Str.take_until([](char C) { return C == '&'; });
OffsetStr.getAsInteger(10, O);
Str = Str.drop_front(OffsetStr.size());
if (!Str.consume_front("&size="))
return createStringError(object_error::parse_failed,
"Reading 'size' in URI");
Str.getAsInteger(10, S);
std::unique_ptr<OffloadBundleURI> OffloadingURI(
new OffloadBundleURI(FilePathname, O, S));
return std::move(OffloadingURI);
}
static Expected<std::unique_ptr<OffloadBundleURI>>
createMemoryURI(StringRef Str) {
// TODO: add parseMemoryURI type
return createStringError(object_error::parse_failed,
"Memory Type URI is not currently supported.");
}
StringRef getFileName() const { return FileName; }
};
/// Extracts fat binary in binary clang-offload-bundler format from object \p
/// Obj and return it in \p Bundles
LLVM_ABI Error extractOffloadBundleFatBinary(
const ObjectFile &Obj, SmallVectorImpl<OffloadBundleFatBin> &Bundles);
/// 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(const ObjectFile &Source, size_t Offset,
size_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);
} // namespace object
} // namespace llvm
#endif