|
30 | 30 | #include "llvm/Support/Error.h"
|
31 | 31 | #include "llvm/Support/ErrorOr.h"
|
32 | 32 | #include "llvm/Support/FileSystem.h"
|
33 |
| -#include "llvm/Support/FileUtilities.h" |
34 | 33 | #include "llvm/Support/MemoryBuffer.h"
|
35 | 34 | #include "llvm/Support/Path.h"
|
36 | 35 | #include "llvm/Support/Program.h"
|
@@ -365,6 +364,41 @@ class BinaryFileHandler final : public FileHandler {
|
365 | 364 | }
|
366 | 365 | };
|
367 | 366 |
|
| 367 | +namespace { |
| 368 | + |
| 369 | +// This class implements a list of temporary files that are removed upon |
| 370 | +// object destruction. |
| 371 | +class TempFileHandlerRAII { |
| 372 | +public: |
| 373 | + ~TempFileHandlerRAII() { |
| 374 | + for (const auto &File : Files) |
| 375 | + sys::fs::remove(File); |
| 376 | + } |
| 377 | + |
| 378 | + // Creates temporary file with given contents. |
| 379 | + Expected<StringRef> Create(Optional<ArrayRef<char>> Contents) { |
| 380 | + SmallString<128u> File; |
| 381 | + if (std::error_code EC = |
| 382 | + sys::fs::createTemporaryFile("clang-offload-bundler", "tmp", File)) |
| 383 | + return createFileError(File, EC); |
| 384 | + Files.push_back(File); |
| 385 | + |
| 386 | + if (Contents) { |
| 387 | + std::error_code EC; |
| 388 | + raw_fd_ostream OS(File, EC); |
| 389 | + if (EC) |
| 390 | + return createFileError(File, EC); |
| 391 | + OS.write(Contents->data(), Contents->size()); |
| 392 | + } |
| 393 | + return Files.back(); |
| 394 | + } |
| 395 | + |
| 396 | +private: |
| 397 | + SmallVector<SmallString<128u>, 4u> Files; |
| 398 | +}; |
| 399 | + |
| 400 | +} // end anonymous namespace |
| 401 | + |
368 | 402 | /// Handler for object files. The bundles are organized by sections with a
|
369 | 403 | /// designated name.
|
370 | 404 | ///
|
@@ -433,11 +467,16 @@ class ObjectFileHandler final : public FileHandler {
|
433 | 467 | Error ReadBundleEnd(MemoryBuffer &Input) final { return Error::success(); }
|
434 | 468 |
|
435 | 469 | Error ReadBundle(raw_fd_ostream &OS, MemoryBuffer &Input) final {
|
436 |
| - Expected<StringRef> Content = CurrentSection->getContents(); |
437 |
| - if (!Content) |
438 |
| - return Content.takeError(); |
| 470 | + Expected<StringRef> ContentOrErr = CurrentSection->getContents(); |
| 471 | + if (!ContentOrErr) |
| 472 | + return ContentOrErr.takeError(); |
| 473 | + StringRef Content = *ContentOrErr; |
| 474 | + |
| 475 | + // Copy fat object contents to the output when extracting host bundle. |
| 476 | + if (Content.size() == 1u && Content.front() == 0) |
| 477 | + Content = StringRef(Input.getBufferStart(), Input.getBufferSize()); |
439 | 478 |
|
440 |
| - OS.write(Content->data(), Content->size()); |
| 479 | + OS.write(Content.data(), Content.size()); |
441 | 480 | return Error::success();
|
442 | 481 | }
|
443 | 482 |
|
@@ -486,22 +525,37 @@ class ObjectFileHandler final : public FileHandler {
|
486 | 525 | // to pass down to llvm-objcopy.
|
487 | 526 | OS.close();
|
488 | 527 |
|
| 528 | + // Temporary files that need to be removed. |
| 529 | + TempFileHandlerRAII TempFiles; |
| 530 | + |
489 | 531 | // Create an intermediate temporary file to save object after the first
|
490 | 532 | // llvm-objcopy run.
|
491 |
| - SmallString<128u> IntermediateObj; |
492 |
| - if (std::error_code EC = sys::fs::createTemporaryFile( |
493 |
| - "clang-offload-bundler", "tmp", IntermediateObj)) |
494 |
| - return createFileError(IntermediateObj, EC); |
495 |
| - FileRemover IntermediateObjRemover(IntermediateObj); |
| 533 | + Expected<SmallString<128u>> IntermediateObjOrErr = TempFiles.Create(None); |
| 534 | + if (!IntermediateObjOrErr) |
| 535 | + return IntermediateObjOrErr.takeError(); |
| 536 | + const SmallString<128u> &IntermediateObj = *IntermediateObjOrErr; |
496 | 537 |
|
497 | 538 | // Compose llvm-objcopy command line for add target objects' sections.
|
498 | 539 | BumpPtrAllocator Alloc;
|
499 | 540 | StringSaver SS{Alloc};
|
500 | 541 | SmallVector<StringRef, 8u> ObjcopyArgs{"llvm-objcopy"};
|
501 |
| - for (unsigned I = 0; I < NumberOfInputs; ++I) |
| 542 | + for (unsigned I = 0; I < NumberOfInputs; ++I) { |
| 543 | + StringRef InputFile = InputFileNames[I]; |
| 544 | + if (I == HostInputIndex) { |
| 545 | + // Special handling for the host bundle. We do not need to add a |
| 546 | + // standard bundle for the host object since we are going to use fat |
| 547 | + // object as a host object. Therefore use dummy contents (one zero byte) |
| 548 | + // when creating section for the host bundle. |
| 549 | + Expected<StringRef> TempFileOrErr = TempFiles.Create(ArrayRef<char>(0)); |
| 550 | + if (!TempFileOrErr) |
| 551 | + return TempFileOrErr.takeError(); |
| 552 | + InputFile = *TempFileOrErr; |
| 553 | + } |
| 554 | + |
502 | 555 | ObjcopyArgs.push_back(SS.save(Twine("--add-section=") +
|
503 | 556 | OFFLOAD_BUNDLER_MAGIC_STR + TargetNames[I] +
|
504 |
| - "=" + InputFileNames[I])); |
| 557 | + "=" + InputFile)); |
| 558 | + } |
505 | 559 | ObjcopyArgs.push_back(InputFileNames[HostInputIndex]);
|
506 | 560 | ObjcopyArgs.push_back(IntermediateObj);
|
507 | 561 |
|
|
0 commit comments