LLVM 24.0.0git
OffloadBinary.h
Go to the documentation of this file.
1//===- OffloadBinary.h - Utilities for handling offloading code -----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the binary format used for bundling device metadata with
10// an associated device image. The data can then be stored inside a host object
11// file to create a fat binary and read by the linker. This is intended to be a
12// thin wrapper around the image itself. If this format becomes sufficiently
13// complex it should be moved to a standard binary format like msgpack or ELF.
14//
15//===----------------------------------------------------------------------===//
16
17#ifndef LLVM_OBJECT_OFFLOADBINARY_H
18#define LLVM_OBJECT_OFFLOADBINARY_H
19
20#include "llvm/ADT/ArrayRef.h"
21#include "llvm/ADT/MapVector.h"
23#include "llvm/ADT/StringRef.h"
24#include "llvm/Object/Binary.h"
27#include "llvm/Support/Error.h"
29#include <memory>
30
31namespace llvm {
32
33namespace object {
34
35/// The producer of the associated offloading image.
38 OFK_OpenMP = (1 << 0),
39 OFK_Cuda = (1 << 1),
40 OFK_HIP = (1 << 2),
41 OFK_SYCL = (1 << 3),
42 OFK_LAST = (1 << 4),
43};
44
45/// The type of contents the offloading image contains.
57
58/// Flags associated with the Entry.
61 // Entry doesn't contain an image. Used to keep metadata only entries.
62 OIF_Metadata = (1 << 0),
63};
64
65/// A simple binary serialization of an offloading file. We use this format to
66/// embed the offloading image into the host executable so it can be extracted
67/// and used by the linker.
68///
69/// Many of these could be stored in the same section by the time the linker
70/// sees it so we mark this information with a header. The version is used to
71/// detect ABI stability and the size is used to find other offloading entries
72/// that may exist in the same section. All offsets are given as absolute byte
73/// offsets from the beginning of the file.
74class OffloadBinary : public Binary {
75public:
78
79 /// The current version of the binary used for backwards compatibility.
80 static const uint32_t Version = 3;
81
82 /// The offloading metadata that will be serialized to a memory buffer.
90
91 struct Header {
92 uint8_t Magic[4] = {0x10, 0xFF, 0x10, 0xAD}; // 0x10FF10AD magic bytes.
93 uint32_t Version = OffloadBinary::Version; // Version identifier.
94 uint64_t Size; // Size in bytes of this entire binary.
95 uint64_t EntriesOffset; // Offset in bytes to the start of entries block.
96 uint64_t EntriesCount; // Number of metadata entries in the binary.
97 uint64_t InflatedSize; // Original size of the binary if compressed.
98 };
99
100 struct Entry {
101 ImageKind TheImageKind; // The kind of the image stored.
102 OffloadKind TheOffloadKind; // The producer of this image.
103 uint32_t Flags; // Additional flags associated with the entry.
104 uint64_t StringOffset; // Offset in bytes to the string map.
105 uint64_t NumStrings; // Number of entries in the string map.
106 uint64_t ImageOffset; // Offset in bytes of the actual binary image.
107 uint64_t ImageSize; // Size in bytes of the binary image.
108 };
109
110 struct StringEntry {
113 uint64_t ValueSize; // Size of the value in bytes.
114 };
115
120
121 /// True if \p Buf is a compressed offload package, false otherwise.
122 LLVM_ABI static bool isCompressed(MemoryBufferRef Buf);
123
124 /// Attempt to extract and validate the header from the offloading binary in
125 /// \p Buf.
128
129 /// Attempt to parse the offloading binary stored in \p Buf.
130 /// For version 1 binaries, always returns a single OffloadBinary.
131 /// For version 2+ binaries:
132 /// - If \p Index is provided, returns the OffloadBinary at that index.
133 /// - If \p Index is std::nullopt, returns all OffloadBinary entries.
134 /// \param Buf The memory buffer containing the offload binary.
135 /// \param Index Optional index to select a specific entry. If not provided,
136 /// all entries are returned (version 2+ only).
137 /// \returns An array of unique pointers to OffloadBinary objects, or an
138 /// error.
140 create(MemoryBufferRef Buf, std::optional<uint64_t> Index = std::nullopt);
141
142 /// Serialize the contents of \p OffloadingData to a binary buffer to be read
143 /// later.
145 write(ArrayRef<OffloadingImage> OffloadingData);
146
147 /// Serialize \p OffloadingData to a compressed binary with \p Compress.
149 write(ArrayRef<OffloadingImage> OffloadingData, compression::Params Compress);
150
151 static uint64_t getAlignment() { return 8; }
152
153 ImageKind getImageKind() const { return TheEntry->TheImageKind; }
154 OffloadKind getOffloadKind() const { return TheEntry->TheOffloadKind; }
155 uint32_t getVersion() const { return TheHeader->Version; }
156 uint32_t getFlags() const { return TheEntry->Flags; }
157 uint64_t getSize() const { return TheHeader->Size; }
158 uint64_t getIndex() const { return Index; }
159
160 StringRef getTriple() const { return getString("triple"); }
161 StringRef getArch() const { return getString("arch"); }
163 return StringRef(&Buffer[TheEntry->ImageOffset], TheEntry->ImageSize);
164 }
165
166 // Iterator over all the key and value pairs in the binary.
167 string_iterator_range strings() const { return StringData; }
168
169 StringRef getString(StringRef Key) const { return StringData.lookup(Key); }
170
171 static bool classof(const Binary *V) { return V->isOffloadFile(); }
172
173private:
174 OffloadBinary(std::shared_ptr<MemoryBuffer> Owned, const Header *TheHeader,
175 const Entry *TheEntry, const uint64_t Index = 0)
176 : Binary(Binary::ID_Offload, *Owned), OwnedBuffer(std::move(Owned)),
177 Buffer(OwnedBuffer->getBufferStart()), TheHeader(TheHeader),
178 TheEntry(TheEntry), Index(Index) {
179 // StringEntryV1 and StringEntry have ABI compatible Key/ValueOffset fields,
180 // but different sizes, so we need to manually calculate offset.
181 const char *StringMapBegin = &Buffer[TheEntry->StringOffset];
182 const size_t StringEntrySize =
183 TheHeader->Version == 1 ? sizeof(StringEntryV1) : sizeof(StringEntry);
184 for (uint64_t I = 0, E = TheEntry->NumStrings; I != E; ++I) {
185 const char *StringEntryPtr = StringMapBegin + I * StringEntrySize;
186 const StringEntryV1 *EntryV1 =
187 reinterpret_cast<const StringEntryV1 *>(StringEntryPtr);
188 StringRef Key = &Buffer[EntryV1->KeyOffset];
189 if (TheHeader->Version == 1) {
190 StringData[Key] = &Buffer[EntryV1->ValueOffset];
191 } else {
192 const StringEntry *Entry =
193 reinterpret_cast<const StringEntry *>(StringEntryPtr);
194 StringData[Key] =
195 StringRef(&Buffer[Entry->ValueOffset], Entry->ValueSize);
196 }
197 }
198 }
199
200 OffloadBinary(const OffloadBinary &Other) = delete;
201
202 /// Owned uncompressed binary. Shared between entries parsed from one blob.
203 std::shared_ptr<MemoryBuffer> OwnedBuffer;
204 /// Map from keys to offsets in the binary.
205 MapVector<StringRef, StringRef> StringData;
206 /// Raw pointer to the MemoryBufferRef for convenience.
207 const char *Buffer;
208 /// Location of the header within the binary.
209 const Header *TheHeader;
210 /// Location of the metadata entries within the binary.
211 const Entry *TheEntry;
212 /// Index of the entry in the list of entries serialized in the Buffer.
213 const uint64_t Index;
214};
215
216/// A handle to a single OffloadBinary.
218public:
219 using TargetID = std::pair<StringRef, StringRef>;
220
221 OffloadFile() = default;
222 OffloadFile(std::unique_ptr<OffloadBinary> Binary)
223 : Binary(std::move(Binary)) {}
224
225 OffloadBinary *getBinary() { return Binary.get(); }
226 const OffloadBinary *getBinary() const { return Binary.get(); }
227
228 /// Make a deep copy of this offloading file.
230 auto NewBinaryOrErr = OffloadBinary::create(
231 getBinary()->getMemoryBufferRef(), getBinary()->getIndex());
232 assert(NewBinaryOrErr && "Failed to parse a copy of the binary?");
233 if (!NewBinaryOrErr)
234 llvm::consumeError(NewBinaryOrErr.takeError());
235 return OffloadFile(std::move((*NewBinaryOrErr)[0]));
236 }
237
238 /// We use the Triple and Architecture pair to group linker inputs together.
239 /// This conversion function lets us use these inputs in a hash-map.
240 operator TargetID() const {
241 return std::make_pair(getBinary()->getTriple(), getBinary()->getArch());
242 }
243
244private:
245 std::unique_ptr<OffloadBinary> Binary;
246};
247
248/// Extracts embedded device offloading code from a memory \p Buffer to a list
249/// of \p Binaries.
250LLVM_ABI Error extractOffloadBinaries(MemoryBufferRef Buffer,
252
253/// Convert a string \p Name to an image kind.
254LLVM_ABI ImageKind getImageKind(StringRef Name);
255
256/// Convert an image kind to its string representation.
257LLVM_ABI StringRef getImageKindName(ImageKind Name);
258
259/// Convert a string \p Name to an offload kind.
260LLVM_ABI OffloadKind getOffloadKind(StringRef Name);
261
262/// Convert an offload kind to its string representation.
263LLVM_ABI StringRef getOffloadKindName(OffloadKind Name);
264
265/// Returns true if an image built for target \p Provided can provide the device
266/// code for a request for target \p Requested. This is directional: a
267/// feature-unspecified or generic image serves a more specific request (e.g. a
268/// generic static-archive member pulled into a specific device-image group),
269/// but not vice versa. For AMDGPU a target id is a string conforming to the
270/// following BNF syntax:
271///
272/// target-id ::= '<arch> ( : <feature> ( '+' | '-' ) )*'
273///
274/// The features 'xnack' and 'sramecc' are currently supported. These can be in
275/// the state of on, off, and any when unspecified. A provided target marked as
276/// any can bind with either on or off.
277LLVM_ABI bool areTargetsCompatible(const OffloadFile::TargetID &Provided,
278 const OffloadFile::TargetID &Requested);
279
280/// Returns true if \p LHS and \p RHS denote the same logical target, i.e. the
281/// same processor and features.
282LLVM_ABI bool areTargetsEquivalent(const OffloadFile::TargetID &LHS,
283 const OffloadFile::TargetID &RHS);
284
285} // namespace object
286
287} // namespace llvm
288#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_ABI
Definition Compiler.h:211
#define I(x, y, z)
Definition MD5.cpp:57
This file implements a map that provides insertion order iteration.
This file defines the SmallString class.
Value * RHS
Value * LHS
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
Tagged union holding either a T or a Error.
Definition Error.h:485
This class implements a map that also provides access to all stored values in a deterministic order.
Definition MapVector.h:39
typename VectorType::const_iterator const_iterator
Definition MapVector.h:46
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
A range adaptor for a pair of iterators.
Binary(unsigned int Type, MemoryBufferRef Source)
Definition Binary.cpp:20
A simple binary serialization of an offloading file.
static uint64_t getAlignment()
OffloadKind getOffloadKind() const
iterator_range< string_iterator > string_iterator_range
static LLVM_ABI Expected< SmallVector< std::unique_ptr< OffloadBinary > > > create(MemoryBufferRef Buf, std::optional< uint64_t > Index=std::nullopt)
Attempt to parse the offloading binary stored in Buf.
static LLVM_ABI SmallString< 0 > write(ArrayRef< OffloadingImage > OffloadingData)
Serialize the contents of OffloadingData to a binary buffer to be read later.
StringRef getString(StringRef Key) const
static LLVM_ABI bool isCompressed(MemoryBufferRef Buf)
True if Buf is a compressed offload package, false otherwise.
static LLVM_ABI Expected< const Header * > extractHeader(MemoryBufferRef Buf)
Attempt to extract and validate the header from the offloading binary in Buf.
StringRef getTriple() const
ImageKind getImageKind() const
static bool classof(const Binary *V)
string_iterator_range strings() const
static const uint32_t Version
The current version of the binary used for backwards compatibility.
MapVector< StringRef, StringRef >::const_iterator string_iterator
const OffloadBinary * getBinary() const
std::pair< StringRef, StringRef > TargetID
OffloadFile copy() const
Make a deep copy of this offloading file.
OffloadFile(std::unique_ptr< OffloadBinary > Binary)
OffloadBinary * getBinary()
StringMapEntry< EmptyStringSetTag > StringEntry
StringEntry keeps data of the string: the length, external offset and a string body which is placed r...
Definition StringPool.h:23
OffloadEntryFlags
Flags associated with the Entry.
OffloadKind
The producer of the associated offloading image.
ImageKind
The type of contents the offloading image contains.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
@ Other
Any other memory.
Definition ModRef.h:68
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1933
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1106
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
The offloading metadata that will be serialized to a memory buffer.
std::unique_ptr< MemoryBuffer > Image
MapVector< StringRef, StringRef > StringData