LLVM: lib/Object/OffloadBundle.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
24
25using namespace llvm;
27
29 "Timer group for offload bundler");
30
31
32
36
38 size_t NextbundleStart = 0;
40 std::unique_ptr Buffer;
41
42
45 Buffer =
47 false);
48
51 Magic = "CCOB";
52
53 NextbundleStart = (*Buffer).getBuffer().find(Magic, Magic.size());
55 NextbundleStart = (*Buffer).getBuffer().size();
56
59 (*Buffer).getBuffer().take_front(NextbundleStart), FileName,
60 false);
61 if (std::error_code EC = CodeOrErr.getError())
63
66 if (!DecompressedBufferOrErr)
69
71 **DecompressedBufferOrErr, Offset, FileName, true);
72 if (!FatBundleOrErr)
73 return FatBundleOrErr.takeError();
74
75
76 Bundles.emplace_back(std::move(**FatBundleOrErr));
77
80
81
83 *Buffer, SectionOffset + Offset, FileName);
84 if (!FatBundleOrErr)
85 return FatBundleOrErr.takeError();
86
87
88 Bundles.emplace_back(std::move(**FatBundleOrErr));
89
90 Magic = "__CLANG_OFFLOAD_BUNDLE__";
91 NextbundleStart = (*Buffer).getBuffer().find(Magic, Magic.size());
92 }
93
95 Offset += NextbundleStart;
96 }
97
99}
100
104
106
107
111
112
113 if (auto EC = Reader.readInteger(NumOfEntries))
115
116 NumberOfEntries = NumOfEntries;
117
118
119 for (uint64_t I = 0; I < NumOfEntries; I++) {
124
126 return Err;
127
129 return Err;
130
132 return Err;
133
135 return Err;
136
137 auto Entry = std::make_unique(
138 EntryOffset + SectionOffset, EntrySize, EntryIDSize, EntryID);
139
140 Entries.push_back(*Entry);
141 }
142
144}
145
148 StringRef FileName, bool Decompress) {
151
152
157
158 std::unique_ptr TheBundle(
160
161
163 TheBundle->readEntries(Buf.getBuffer(), Decompress ? 0 : SectionOffset);
164 if (Err)
165 return Err;
166
167 return std::move(TheBundle);
168}
169
171
173
174 if (Entry.Size == 0)
175 continue;
176
177
178
180 "-size" + itostr(Entry.Size) + ".co";
183 return Err;
184 }
185
187}
188
191 assert((Obj.isELF() || Obj.isCOFF()) && "Invalid file type");
192
193
194 for (SectionRef Sec : Obj.sections()) {
196 if (!Buffer)
198
199
203
205 if (Obj.isELF()) {
207 } else if (Obj.isCOFF())
209 "COFF object files not supported");
210
213 Obj.getFileName(), Bundles))
214 return Err;
215 }
216 }
218}
219
224
225 if (!BufferOrErr)
227
230 return Err;
231
232 std::unique_ptr Buf = std::move(*BufferOrErr);
233 std::copy(InputBuffOrErr->getBufferStart() + Offset,
234 InputBuffOrErr->getBufferStart() + Offset + Size,
235 Buf->getBufferStart());
236 if (Error E = Buf->commit())
237 return E;
238
240}
241
246 if (!BufferOrErr)
248
249 std::unique_ptr Buf = std::move(*BufferOrErr);
252
253 return Buf->commit();
254}
255
256
257
259
262 if (!UriOrErr)
264
266 std::string OutputFile = Uri.FileName.str();
267 OutputFile +=
269
270
272 if (!ObjOrErr)
273 return ObjOrErr.takeError();
274
275 auto Obj = ObjOrErr->getBinary();
278 return Err;
279
281}
282
283
285 std::string Num = std::to_string(Value);
290 }
291 return Num;
292}
293
294Expected<std::unique_ptr>
300 Timer HashTimer("Hash Calculation Timer", "Hash calculation time",
302 if (VerboseStream)
304 MD5 Hash;
307 Hash.final(Result);
308 uint64_t TruncatedHash = Result.low();
309 if (VerboseStream)
311
314 reinterpret_cast<const uint8_t *>(Input.getBuffer().data()),
315 Input.getBuffer().size());
316 Timer CompressTimer("Compression Timer", "Compression time",
318 if (VerboseStream)
321 if (VerboseStream)
323
325
326
327 uint64_t UncompressedSize64 = Input.getBuffer().size();
329
330
332
333 if (UncompressedSize64 > std::numeric_limits<uint32_t>::max())
334 return createStringError("uncompressed size (%llu) exceeds version 2 "
335 "unsigned 32-bit integer limit",
336 UncompressedSize64);
337 TotalFileSize64 = MagicNumber.size() + sizeof(uint32_t) + sizeof(Version) +
338 sizeof(CompressionMethod) + sizeof(uint32_t) +
339 sizeof(TruncatedHash) + CompressedBuffer.size();
340 if (TotalFileSize64 > std::numeric_limits<uint32_t>::max())
341 return createStringError("total file size (%llu) exceeds version 2 "
342 "unsigned 32-bit integer limit",
343 TotalFileSize64);
344
345 } else {
346 TotalFileSize64 = MagicNumber.size() + sizeof(uint64_t) + sizeof(Version) +
347 sizeof(CompressionMethod) + sizeof(uint64_t) +
348 sizeof(TruncatedHash) + CompressedBuffer.size();
349 }
350
353 OS << MagicNumber;
355 OS.write(reinterpret_cast<const char *>(&CompressionMethod),
356 sizeof(CompressionMethod));
357
358
360 uint32_t TotalFileSize32 = static_cast<uint32_t>(TotalFileSize64);
361 uint32_t UncompressedSize32 = static_cast<uint32_t>(UncompressedSize64);
362 OS.write(reinterpret_cast<const char *>(&TotalFileSize32),
363 sizeof(TotalFileSize32));
364 OS.write(reinterpret_cast<const char *>(&UncompressedSize32),
365 sizeof(UncompressedSize32));
366 } else {
367 OS.write(reinterpret_cast<const char *>(&TotalFileSize64),
368 sizeof(TotalFileSize64));
369 OS.write(reinterpret_cast<const char *>(&UncompressedSize64),
370 sizeof(UncompressedSize64));
371 }
372
373 OS.write(reinterpret_cast<const char *>(&TruncatedHash),
374 sizeof(TruncatedHash));
375 OS.write(reinterpret_cast<const char *>(CompressedBuffer.data()),
376 CompressedBuffer.size());
377
378 if (VerboseStream) {
380 double CompressionRate =
381 static_cast<double>(UncompressedSize64) / CompressedBuffer.size();
383 double CompressionSpeedMBs =
384 (UncompressedSize64 / (1024.0 * 1024.0)) / CompressionTimeSeconds;
385 *VerboseStream << "Compressed bundle format version: " << Version << "\n"
386 << "Total file size (including headers): "
388 << "Compression method used: " << MethodUsed << "\n"
389 << "Compression level: " << P.level << "\n"
390 << "Binary size before compression: "
392 << "Binary size after compression: "
394 << "Compression rate: " << format("%.2lf", CompressionRate)
395 << "\n"
396 << "Compression ratio: "
397 << format("%.2lf%%", 100.0 / CompressionRate) << "\n"
398 << "Compression speed: "
399 << format("%.2lf MB/s", CompressionSpeedMBs) << "\n"
400 << "Truncated MD5 hash: " << format_hex(TruncatedHash, 16)
401 << "\n";
402 }
403
406}
407
408
409
444
445
447 switch (Version) {
448 case 1:
450 case 2:
452 case 3:
454 default:
456 }
457}
458
459ExpectedCompressedOffloadBundle::CompressedBundleHeader
463
465 std::memcpy(&Header, Blob.data(), std::min(Blob.size(), sizeof(Header)));
466
468 Normalized.Version = Header.Common.Version;
469
471
472 if (Blob.size() < RequiredSize)
473 return createStringError("compressed bundle header size too small");
474
475 switch (Normalized.Version) {
476 case 1:
478 Normalized.Hash = Header.V1.Hash;
479 break;
480 case 2:
481 Normalized.FileSize = Header.V2.FileSize;
483 Normalized.Hash = Header.V2.Hash;
484 break;
485 case 3:
486 Normalized.FileSize = Header.V3.FileSize;
488 Normalized.Hash = Header.V3.Hash;
489 break;
490 default:
492 }
493
494
495 switch (Header.Common.Method) {
500 break;
501 default:
503 }
504
505 return Normalized;
506}
507
512
513
516
518 if (VerboseStream)
519 *VerboseStream << "Uncompressed bundle\n";
521 }
522
525 if (!HeaderOrErr)
527
529 unsigned ThisVersion = Normalized.Version;
531
533
534 size_t TotalFileSize = Normalized.FileSize.value_or(0);
536 auto StoredHash = Normalized.Hash;
537
538 Timer DecompressTimer("Decompression Timer", "Decompression time",
540 if (VerboseStream)
542
545 Blob.substr(HeaderSize, TotalFileSize - HeaderSize);
546
549 DecompressedData, UncompressedSize))
550 return createStringError("could not decompress embedded file contents: " +
551 toString(std::move(DecompressionError)));
552
553 if (VerboseStream) {
555
556 double DecompressionTimeSeconds =
558
559
560 Timer HashRecalcTimer("Hash Recalculation Timer", "Hash recalculation time",
563 MD5 Hash;
566 Hash.final(Result);
567 uint64_t RecalculatedHash = Result.low();
569 bool HashMatch = (StoredHash == RecalculatedHash);
570
571 double CompressionRate =
572 static_cast<double>(UncompressedSize) / CompressedData.size();
573 double DecompressionSpeedMBs =
574 (UncompressedSize / (1024.0 * 1024.0)) / DecompressionTimeSeconds;
575
576 *VerboseStream << "Compressed bundle format version: " << ThisVersion
577 << "\n";
578 if (ThisVersion >= 2)
579 *VerboseStream << "Total file size (from header): "
581 *VerboseStream
582 << "Decompression method: "
584 << "\n"
585 << "Size before decompression: "
587 << "Size after decompression: " << formatWithCommas(UncompressedSize)
588 << " bytes\n"
589 << "Compression rate: " << format("%.2lf", CompressionRate) << "\n"
590 << "Compression ratio: " << format("%.2lf%%", 100.0 / CompressionRate)
591 << "\n"
592 << "Decompression speed: "
593 << format("%.2lf MB/s", DecompressionSpeedMBs) << "\n"
594 << "Stored hash: " << format_hex(StoredHash, 16) << "\n"
595 << "Recalculated hash: " << format_hex(RecalculatedHash, 16) << "\n"
596 << "Hashes match: " << (HashMatch ? "Yes" : "No") << "\n";
597 }
598
600}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_PACKED_START
Module.h This file contains the declarations for the Module class.
static LLVM_PACKED_END size_t getHeaderSize(uint16_t Version)
Definition OffloadBundle.cpp:446
Error extractOffloadBundle(MemoryBufferRef Contents, uint64_t SectionOffset, StringRef FileName, SmallVectorImpl< OffloadBundleFatBin > &Bundles)
Definition OffloadBundle.cpp:33
static std::string formatWithCommas(unsigned long long Value)
Definition OffloadBundle.cpp:284
static TimerGroup OffloadBundlerTimerGroup("Offload Bundler Timer Group", "Timer group for offload bundler")
The Input class is used to parse a yaml document into in-memory structs and vectors.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Provides read only access to a subclass of BinaryStream.
Error readInteger(T &Dest)
Read an integer of the specified endianness into Dest and update the stream's offset.
LLVM_ABI Error readFixedString(StringRef &Dest, uint32_t Length)
Read a Length byte string into Dest.
Represents either an error or a value T.
std::error_code getError() const
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
static LLVM_ABI Expected< std::unique_ptr< FileOutputBuffer > > create(StringRef FilePath, size_t Size, unsigned Flags=0)
Factory method to create an OutputBuffer object which manages a read/write buffer of the specified si...
LLVM_ABI void update(ArrayRef< uint8_t > Data)
Updates the hash for the byte stream provided.
LLVM_ABI void final(MD5Result &Result)
Finishes off the hash and puts the result in result.
size_t getBufferSize() const
const char * getBufferStart() const
StringRef getBuffer() const
This interface provides simple read-only access to a block of memory, and provides simple methods for...
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
pointer data()
Return a pointer to the vector's buffer, even if empty().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
static constexpr size_t npos
std::string str() const
str - Get the contents as an std::string.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
double getWallTime() const
The TimerGroup class is used to group together related timers into a single report that is printed wh...
This class is used to track the amount of time spent between invocations of its startTimer()/stopTime...
LLVM_ABI void stopTimer()
Stop the timer.
LLVM_ABI void startTimer()
Start the timer running.
TimeRecord getTotalTime() const
Return the duration for which this timer has been running.
LLVM Value Representation.
static llvm::Expected< std::unique_ptr< llvm::MemoryBuffer > > decompress(const llvm::MemoryBuffer &Input, raw_ostream *VerboseStream=nullptr)
Definition OffloadBundle.cpp:509
static llvm::Expected< std::unique_ptr< llvm::MemoryBuffer > > compress(llvm::compression::Params P, const llvm::MemoryBuffer &Input, uint16_t Version, raw_ostream *VerboseStream=nullptr)
Definition OffloadBundle.cpp:295
uint64_t getOffset() const
This class is the base class for all object file types.
static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)
LLVM_ABI Error readEntries(StringRef Section, uint64_t SectionOffset)
Definition OffloadBundle.cpp:101
OffloadBundleFatBin(MemoryBufferRef Source, StringRef File, bool Decompress=false)
LLVM_ABI Error extractBundle(const ObjectFile &Source)
Definition OffloadBundle.cpp:170
StringRef getFileName() const
static LLVM_ABI Expected< std::unique_ptr< OffloadBundleFatBin > > create(MemoryBufferRef, uint64_t SectionOffset, StringRef FileName, bool Decompress=false)
Definition OffloadBundle.cpp:147
This is a value type class that represents a single section in the list of sections in the object fil...
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & write(unsigned char C)
A raw_ostream that writes to an SmallVector or SmallString.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI bool isAvailable()
LLVM_ABI bool isAvailable()
LLVM_ABI Error decompress(DebugCompressionType T, ArrayRef< uint8_t > Input, uint8_t *Output, size_t UncompressedSize)
LLVM_ABI void compress(Params P, ArrayRef< uint8_t > Input, SmallVectorImpl< uint8_t > &Output)
LLVM_ABI Error extractCodeObject(const ObjectFile &Source, int64_t Offset, int64_t Size, StringRef OutputFileName)
Extract code object memory from the given Source object file at Offset and of Size,...
Definition OffloadBundle.cpp:220
LLVM_ABI Error extractOffloadBundleByURI(StringRef URIstr)
Extracts an Offload Bundle Entry given by URI.
Definition OffloadBundle.cpp:258
LLVM_ABI Error extractOffloadBundleFatBinary(const ObjectFile &Obj, SmallVectorImpl< OffloadBundleFatBin > &Bundles)
Extracts fat binary in binary clang-offload-bundler format from object Obj and return it in Bundles.
Definition OffloadBundle.cpp:189
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI file_magic identify_magic(StringRef magic)
Identify the type of a binary file based on how magical it is.
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
ArrayRef< CharT > arrayRefFromStringRef(StringRef Input)
Construct a string ref from an array ref of unsigned chars.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
FunctionAddr VTableAddr uintptr_t uintptr_t Version
FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false)
format_hex - Output N as a fixed width hexadecimal.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
StringRef toStringRef(bool B)
Construct a string ref from a boolean.
std::string itostr(int64_t X)
@ offload_bundle
Clang offload bundle file.
@ offload_bundle_compressed
Compressed clang offload bundle file.
Bundle entry in binary clang-offload-bundler format.
static Expected< std::unique_ptr< OffloadBundleURI > > createOffloadBundleURI(StringRef Str, UriTypeT Type)