Skip to content

Commit daa2a39

Browse files
author
Salinas, David
authored
Merge pull request #93 from AMD-Lightning-Internal/amd/dev/dsalinas/object-tooling (#216)
Extend LLVM Offloading API Change-Id: Ia1998a568463281e2e687738533f0d662e446140
1 parent d284ddd commit daa2a39

File tree

8 files changed

+1546
-1
lines changed

8 files changed

+1546
-1
lines changed

llvm/include/llvm/Object/OffloadBinary.h

Lines changed: 176 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.
@@ -182,11 +209,160 @@ class OffloadFile : public OwningBinary<OffloadBinary> {
182209
}
183210
};
184211

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

353+
/// Extracts fat binary in binary clang-offload-bundler format from object \p
354+
/// Obj and return it in \p Bundles
355+
Error extractOffloadBundleFatBinary(
356+
const ObjectFile &Obj, SmallVectorImpl<OffloadBundleFatBin> &Bundles);
357+
358+
/// Extract code object memory from the given \p Source object file at \p Offset
359+
/// and of \p Size, and copy into \p OutputFileName.
360+
Error extractCodeObject(const ObjectFile &Source, int64_t Offset, int64_t Size,
361+
StringRef OutputFileName);
362+
363+
/// Extracts an Offload Bundle Entry given by URI
364+
Error extractOffloadBundleByURI(StringRef URIstr);
365+
190366
/// Convert a string \p Name to an image kind.
191367
ImageKind getImageKind(StringRef Name);
192368

llvm/lib/Object/ObjectFile.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,6 @@ ObjectFile::createObjectFile(StringRef ObjectPath) {
212212
if (std::error_code EC = FileOrErr.getError())
213213
return errorCodeToError(EC);
214214
std::unique_ptr<MemoryBuffer> Buffer = std::move(FileOrErr.get());
215-
216215
Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
217216
createObjectFile(Buffer->getMemBufferRef());
218217
if (Error Err = ObjOrErr.takeError())

0 commit comments

Comments
 (0)