Skip to content

Commit 3a10064

Browse files
david-salinasDavid Salinas
authored andcommitted
Extend LLVM Offloading API for binary fatbin Bundles
With the intention to provide a common API for offloading, this extension to the existing LLVM Offloading API adds support for Binary Fatbin Bundles; moving some support from the Clang offloading API. The intention is to add functionality to LLVM tooling for Binary Fatbin Bundles in subsequent commits. Change-Id: I907fdcbcd0545162a0ce1cf17ebf7c9f3a4dbde6
1 parent 70af40b commit 3a10064

File tree

2 files changed

+622
-0
lines changed

2 files changed

+622
-0
lines changed

llvm/include/llvm/Object/OffloadBinary.h

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include "llvm/ADT/SmallString.h"
2222
#include "llvm/ADT/StringRef.h"
2323
#include "llvm/Object/Binary.h"
24+
#include "llvm/Object/ObjectFile.h"
25+
#include "llvm/Support/Compression.h"
2426
#include "llvm/Support/Error.h"
2527
#include "llvm/Support/MemoryBuffer.h"
2628
#include <memory>
@@ -49,6 +51,31 @@ enum ImageKind : uint16_t {
4951
IMG_LAST,
5052
};
5153

54+
class CompressedOffloadBundle {
55+
private:
56+
static inline const size_t MagicSize = 4;
57+
static inline const size_t VersionFieldSize = sizeof(uint16_t);
58+
static inline const size_t MethodFieldSize = sizeof(uint16_t);
59+
static inline const size_t FileSizeFieldSize = sizeof(uint32_t);
60+
static inline const size_t UncompressedSizeFieldSize = sizeof(uint32_t);
61+
static inline const size_t HashFieldSize = sizeof(uint64_t);
62+
static inline const size_t V1HeaderSize =
63+
MagicSize + VersionFieldSize + MethodFieldSize +
64+
UncompressedSizeFieldSize + HashFieldSize;
65+
static inline const size_t V2HeaderSize =
66+
MagicSize + VersionFieldSize + FileSizeFieldSize + MethodFieldSize +
67+
UncompressedSizeFieldSize + HashFieldSize;
68+
static inline const llvm::StringRef MagicNumber = "CCOB";
69+
static inline const uint16_t Version = 2;
70+
71+
public:
72+
static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
73+
compress(llvm::compression::Params P, const llvm::MemoryBuffer &Input,
74+
bool Verbose = false);
75+
static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
76+
decompress(llvm::MemoryBufferRef &Input, bool Verbose = false);
77+
};
78+
5279
/// A simple binary serialization of an offloading file. We use this format to
5380
/// embed the offloading image into the host executable so it can be extracted
5481
/// and used by the linker.
@@ -183,11 +210,137 @@ class OffloadFile : public OwningBinary<OffloadBinary> {
183210
}
184211
};
185212

213+
class OffloadFatBinBundle {
214+
215+
private:
216+
uint64_t Size = 0u;
217+
StringRef FileName;
218+
int64_t NumberOfEntries;
219+
220+
public:
221+
struct BundleEntry {
222+
uint64_t Offset = 0u;
223+
uint64_t Size = 0u;
224+
uint64_t IDLength = 0u;
225+
StringRef ID;
226+
BundleEntry(uint64_t O, uint64_t S, uint64_t I, StringRef T)
227+
: Offset(O), Size(S), IDLength(I), ID(T) {}
228+
void dump(raw_ostream &OS) {
229+
OS << "Offset = " << Offset << ", Size = " << Size
230+
<< ", ID Length = " << IDLength << ", ID = " << ID;
231+
}
232+
void dumpURI(raw_ostream &OS, StringRef filePath) {
233+
OS << ID.data() << "\tfile:\/\/" << filePath << "#offset=" << Offset
234+
<< "&size=" << Size << "\n";
235+
}
236+
};
237+
238+
uint64_t getSize() const { return Size; }
239+
StringRef getFileName() const { return FileName; }
240+
int64_t getNumEntries() const { return NumberOfEntries; }
241+
242+
std::unique_ptr<SmallVector<BundleEntry>> Entries;
243+
static Expected<std::unique_ptr<OffloadFatBinBundle>>
244+
create(MemoryBufferRef, uint64_t SectionOffset, StringRef fileName);
245+
Error extractBundle(const ObjectFile &Source);
246+
247+
Error ReadEntries(StringRef Section, uint64_t SectionOffset);
248+
void DumpEntries() {
249+
SmallVectorImpl<BundleEntry>::iterator it = Entries->begin();
250+
for (int64_t I = 0; I < Entries->size(); I++) {
251+
it->dump(outs());
252+
++it;
253+
}
254+
}
255+
256+
void PrintEntriesAsURI() {
257+
SmallVectorImpl<BundleEntry>::iterator it = Entries->begin();
258+
for (int64_t I = 0; I < NumberOfEntries; I++) {
259+
it->dumpURI(outs(), FileName);
260+
++it;
261+
}
262+
}
263+
264+
OffloadFatBinBundle(MemoryBufferRef Source, StringRef file) : FileName(file) {
265+
NumberOfEntries = 0;
266+
Entries = std::make_unique<SmallVector<BundleEntry>>();
267+
}
268+
};
269+
270+
enum uri_type_t { FILE_URI, MEMORY_URI };
271+
272+
struct OffloadBundleURI {
273+
int64_t Offset = 0;
274+
int64_t Size = 0;
275+
uint64_t ProcessID = 0;
276+
StringRef FileName;
277+
uri_type_t URIType;
278+
279+
// Constructors
280+
// TODO: add a Copy ctor ?
281+
OffloadBundleURI(StringRef file, int64_t off, int64_t size)
282+
: Offset(off), Size(size), ProcessID(0), FileName(file),
283+
URIType(FILE_URI) {}
284+
285+
OffloadBundleURI(StringRef str, uri_type_t type) {
286+
URIType = type;
287+
switch (URIType) {
288+
case FILE_URI:
289+
parseFileName(str);
290+
break;
291+
case MEMORY_URI:
292+
parseMemoryURI(str);
293+
break;
294+
default:
295+
report_fatal_error("Unrecognized URI type.");
296+
}
297+
}
298+
299+
void parseFileName(StringRef str) {
300+
ProcessID = 0;
301+
URIType = FILE_URI;
302+
if (str.consume_front("file://")) {
303+
StringRef FilePathname =
304+
str.take_until([](char c) { return (c == '#') || (c == '?'); });
305+
FileName = FilePathname;
306+
str = str.drop_front(FilePathname.size());
307+
308+
if (str.consume_front("#offset=")) {
309+
StringRef OffsetStr = str.take_until([](char c) { return c == '&'; });
310+
OffsetStr.getAsInteger(10, Offset);
311+
str = str.drop_front(OffsetStr.size());
312+
313+
if (str.consume_front("&size=")) {
314+
Size;
315+
str.getAsInteger(10, Size);
316+
} else
317+
report_fatal_error("Reading 'size' in URI.");
318+
} else
319+
report_fatal_error("Reading 'offset' in URI.");
320+
} else
321+
report_fatal_error("Reading type of URI.");
322+
}
323+
324+
void parseMemoryURI(StringRef str) {
325+
// TODO: add parseMemoryURI type
326+
}
327+
328+
StringRef getFileName() const { return FileName; }
329+
};
330+
186331
/// Extracts embedded device offloading code from a memory \p Buffer to a list
187332
/// of \p Binaries.
188333
Error extractOffloadBinaries(MemoryBufferRef Buffer,
189334
SmallVectorImpl<OffloadFile> &Binaries);
190335

336+
Error extractFatBinaryFromObject(const ObjectFile &Obj,
337+
SmallVectorImpl<OffloadFatBinBundle> &Bundles);
338+
339+
Error extractCodeObject(const ObjectFile &Source, int64_t Offset, int64_t Size,
340+
StringRef OutputFileName);
341+
342+
Error extractURI(StringRef URIstr);
343+
191344
/// Convert a string \p Name to an image kind.
192345
ImageKind getImageKind(StringRef Name);
193346

0 commit comments

Comments
 (0)