Skip to content

Commit c148185

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 920c589 commit c148185

File tree

5 files changed

+753
-0
lines changed

5 files changed

+753
-0
lines changed
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
//===--- OffloadBundle.h - Utilities for handling offloading code -*- C++
2+
//-*-===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===------------------------------------------------------------------------===//
9+
//
10+
// This file contains the binary format used for budingling device metadata with
11+
// an associated device image. The data can then be stored inside a host object
12+
// file to create a fat binary and read by the linker. This is intended to be a
13+
// thin wrapper around the image itself. If this format becomes sufficiently
14+
// complex it should be moved to a standard binary format like msgpack or ELF.
15+
//
16+
//===------------------------------------------------------------------------===//
17+
18+
#ifndef LLVM_OBJECT_OFFLOADBUNDLE_H
19+
#define LLVM_OBJECT_OFFLOADBUNDLE_H
20+
21+
#include "llvm/ADT/MapVector.h"
22+
#include "llvm/ADT/SmallString.h"
23+
#include "llvm/ADT/StringRef.h"
24+
#include "llvm/Object/Binary.h"
25+
#include "llvm/Object/ObjectFile.h"
26+
#include "llvm/Support/Compression.h"
27+
#include "llvm/Support/Error.h"
28+
#include "llvm/Support/MemoryBuffer.h"
29+
#include <memory>
30+
31+
namespace llvm {
32+
33+
namespace object {
34+
35+
class CompressedOffloadBundle {
36+
private:
37+
static inline const size_t MagicSize = 4;
38+
static inline const size_t VersionFieldSize = sizeof(uint16_t);
39+
static inline const size_t MethodFieldSize = sizeof(uint16_t);
40+
static inline const size_t FileSizeFieldSize = sizeof(uint32_t);
41+
static inline const size_t UncompressedSizeFieldSize = sizeof(uint32_t);
42+
static inline const size_t HashFieldSize = sizeof(uint64_t);
43+
static inline const size_t V1HeaderSize =
44+
MagicSize + VersionFieldSize + MethodFieldSize +
45+
UncompressedSizeFieldSize + HashFieldSize;
46+
static inline const size_t V2HeaderSize =
47+
MagicSize + VersionFieldSize + FileSizeFieldSize + MethodFieldSize +
48+
UncompressedSizeFieldSize + HashFieldSize;
49+
static inline const llvm::StringRef MagicNumber = "CCOB";
50+
static inline const uint16_t Version = 2;
51+
52+
public:
53+
static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
54+
compress(llvm::compression::Params P, const llvm::MemoryBuffer &Input,
55+
bool Verbose = false);
56+
static llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
57+
decompress(llvm::MemoryBufferRef &Input, bool Verbose = false);
58+
};
59+
60+
/// Bundle entry in binary clang-offload-bundler format.
61+
struct OffloadBundleEntry {
62+
uint64_t Offset = 0u;
63+
uint64_t Size = 0u;
64+
uint64_t IDLength = 0u;
65+
StringRef ID;
66+
OffloadBundleEntry(uint64_t O, uint64_t S, uint64_t I, StringRef T)
67+
: Offset(O), Size(S), IDLength(I), ID(T) {}
68+
void dumpInfo(raw_ostream &OS) {
69+
OS << "Offset = " << Offset << ", Size = " << Size
70+
<< ", ID Length = " << IDLength << ", ID = " << ID;
71+
}
72+
void dumpURI(raw_ostream &OS, StringRef FilePath) {
73+
OS << ID.data() << "\tfile://" << FilePath << "#offset=" << Offset
74+
<< "&size=" << Size << "\n";
75+
}
76+
};
77+
78+
/// Fat binary embedded in object files in clang-offload-bundler format
79+
class OffloadBundleFatBin {
80+
81+
uint64_t Size = 0u;
82+
StringRef FileName;
83+
uint64_t NumberOfEntries;
84+
SmallVector<OffloadBundleEntry> Entries;
85+
86+
public:
87+
SmallVector<OffloadBundleEntry> getEntries() { return Entries; }
88+
uint64_t getSize() const { return Size; }
89+
StringRef getFileName() const { return FileName; }
90+
uint64_t getNumEntries() const { return NumberOfEntries; }
91+
92+
static Expected<std::unique_ptr<OffloadBundleFatBin>>
93+
create(MemoryBufferRef, uint64_t SectionOffset, StringRef FileName);
94+
Error extractBundle(const ObjectFile &Source);
95+
96+
Error dumpEntryToCodeObject();
97+
98+
Error readEntries(StringRef Section, uint64_t SectionOffset);
99+
void dumpEntries() {
100+
for (OffloadBundleEntry &Entry : Entries)
101+
Entry.dumpInfo(outs());
102+
}
103+
104+
void printEntriesAsURI() {
105+
for (OffloadBundleEntry &Entry : Entries)
106+
Entry.dumpURI(outs(), FileName);
107+
}
108+
109+
OffloadBundleFatBin(MemoryBufferRef Source, StringRef File)
110+
: FileName(File), NumberOfEntries(0),
111+
Entries(SmallVector<OffloadBundleEntry>()) {}
112+
113+
SmallVector<OffloadBundleEntry> entryIDContains(StringRef Str) {
114+
115+
SmallVector<OffloadBundleEntry> Found = SmallVector<OffloadBundleEntry>();
116+
llvm::transform(Entries, std::back_inserter(Found), [Str](auto &X) {
117+
if (X.ID.contains(Str))
118+
return X;
119+
});
120+
return Found;
121+
}
122+
};
123+
124+
enum UriTypeT { FILE_URI, MEMORY_URI };
125+
126+
struct OffloadBundleURI {
127+
int64_t Offset = 0;
128+
int64_t Size = 0;
129+
uint64_t ProcessID = 0;
130+
StringRef FileName;
131+
UriTypeT URIType;
132+
133+
// Constructors
134+
// TODO: add a Copy ctor ?
135+
OffloadBundleURI(StringRef File, int64_t Off, int64_t Size)
136+
: Offset(Off), Size(Size), ProcessID(0), FileName(File),
137+
URIType(FILE_URI) {}
138+
139+
public:
140+
static Expected<std::unique_ptr<OffloadBundleURI>>
141+
createOffloadBundleURI(StringRef Str, UriTypeT Type) {
142+
switch (Type) {
143+
case FILE_URI:
144+
return createFileURI(Str);
145+
break;
146+
case MEMORY_URI:
147+
return createMemoryURI(Str);
148+
break;
149+
default:
150+
return createStringError(object_error::parse_failed,
151+
"Unrecognized URI type");
152+
}
153+
}
154+
155+
static Expected<std::unique_ptr<OffloadBundleURI>>
156+
createFileURI(StringRef Str) {
157+
int64_t O = 0;
158+
int64_t S = 0;
159+
160+
if (!Str.consume_front("file://"))
161+
return createStringError(object_error::parse_failed,
162+
"Reading type of URI");
163+
164+
StringRef FilePathname =
165+
Str.take_until([](char C) { return (C == '#') || (C == '?'); });
166+
Str = Str.drop_front(FilePathname.size());
167+
168+
if (!Str.consume_front("#offset="))
169+
return createStringError(object_error::parse_failed,
170+
"Reading 'offset' in URI");
171+
172+
StringRef OffsetStr = Str.take_until([](char C) { return C == '&'; });
173+
OffsetStr.getAsInteger(10, O);
174+
Str = Str.drop_front(OffsetStr.size());
175+
176+
if (Str.consume_front("&size="))
177+
return createStringError(object_error::parse_failed,
178+
"Reading 'size' in URI");
179+
180+
Str.getAsInteger(10, S);
181+
std::unique_ptr<OffloadBundleURI> OffloadingURI(
182+
new OffloadBundleURI(FilePathname, O, S));
183+
return OffloadingURI;
184+
}
185+
186+
static Expected<std::unique_ptr<OffloadBundleURI>>
187+
createMemoryURI(StringRef Str) {
188+
// TODO: add parseMemoryURI type
189+
return createStringError(object_error::parse_failed,
190+
"Memory Type URI is not currently supported.");
191+
}
192+
193+
StringRef getFileName() const { return FileName; }
194+
};
195+
196+
/// Extracts fat binary in binary clang-offload-bundler format from object \p
197+
/// Obj and return it in \p Bundles
198+
Error extractOffloadBundleFatBinary(
199+
const ObjectFile &Obj, SmallVectorImpl<OffloadBundleFatBin> &Bundles);
200+
201+
/// Extract code object memory from the given \p Source object file at \p Offset
202+
/// and of \p Size, and copy into \p OutputFileName.
203+
Error extractCodeObject(const ObjectFile &Source, int64_t Offset, int64_t Size,
204+
StringRef OutputFileName);
205+
206+
/// Extracts an Offload Bundle Entry given by URI
207+
Error extractOffloadBundleByURI(StringRef URIstr);
208+
209+
} // namespace object
210+
211+
} // namespace llvm
212+
#endif

llvm/lib/Object/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ add_llvm_component_library(LLVMObject
2222
Object.cpp
2323
ObjectFile.cpp
2424
OffloadBinary.cpp
25+
OffloadBundle.cpp
2526
RecordStreamer.cpp
2627
RelocationResolver.cpp
2728
SymbolicFile.cpp

0 commit comments

Comments
 (0)