Skip to content

Commit c53cb2b

Browse files
committed
[Clang][Bundler] Reduce fat object size
Summary: Fat object size has significantly increased after D65819 which changed bundler tool to add host object as a normal bundle to the fat output which almost doubled its size. That patch was fixing the following issues 1. Problems associated with the partial linking - global constructors were not called for partially linking objects which clearly resulted in incorrect behavior. 2. Eliminating "junk" target object sections from the linked binary on the host side. The first problem is no longer relevant because we do not use partial linking for creating fat objects anymore. Target objects sections are now inserted into the resulting fat object with a help of llvm-objcopy tool. The second issue, "junk" sections in the linked host binary, has been fixed in D73408 by adding "exclude" flag to the fat object's sections which contain target objects. This flag tells linker to drop section from the inputs when linking executable or shared library, therefore these sections will not be propagated in the linked binary. Since both problems have been solved, we can revert D65819 changes to reduce fat object size and this patch essentially is doing that. Reviewers: ABataev, alexshap, jdoerfert Reviewed By: ABataev Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D73642
1 parent fcabccd commit c53cb2b

File tree

2 files changed

+69
-15
lines changed

2 files changed

+69
-15
lines changed

clang/test/Driver/clang-offload-bundler.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -253,16 +253,16 @@
253253

254254
// RUN: clang-offload-bundler -type=o -targets=host-%itanium_abi_triple,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -inputs=%t.o,%t.tgt1,%t.tgt2 -outputs=%t.bundle3.o -### 2>&1 \
255255
// RUN: | FileCheck %s -DHOST=%itanium_abi_triple -DINOBJ1=%t.o -DINOBJ2=%t.tgt1 -DINOBJ3=%t.tgt2 -DOUTOBJ=%t.bundle3.o --check-prefix CK-OBJ-CMD
256-
// CK-OBJ-CMD: llvm-objcopy{{(.exe)?}}" "--add-section=__CLANG_OFFLOAD_BUNDLE__host-[[HOST]]=[[INOBJ1]]" "--add-section=__CLANG_OFFLOAD_BUNDLE__openmp-powerpc64le-ibm-linux-gnu=[[INOBJ2]]" "--add-section=__CLANG_OFFLOAD_BUNDLE__openmp-x86_64-pc-linux-gnu=[[INOBJ3]]" "[[INOBJ1]]" "[[TEMPOBJ:.*]]"
256+
// CK-OBJ-CMD: llvm-objcopy{{(.exe)?}}" "--add-section=__CLANG_OFFLOAD_BUNDLE__host-[[HOST]]={{.*}}" "--add-section=__CLANG_OFFLOAD_BUNDLE__openmp-powerpc64le-ibm-linux-gnu=[[INOBJ2]]" "--add-section=__CLANG_OFFLOAD_BUNDLE__openmp-x86_64-pc-linux-gnu=[[INOBJ3]]" "[[INOBJ1]]" "[[TEMPOBJ:.*]]"
257257
// CK-OBJ-CMD: llvm-objcopy{{(.exe)?}}" "--set-section-flags=__CLANG_OFFLOAD_BUNDLE__host-[[HOST]]=readonly,exclude" "--set-section-flags=__CLANG_OFFLOAD_BUNDLE__openmp-powerpc64le-ibm-linux-gnu=readonly,exclude" "--set-section-flags=__CLANG_OFFLOAD_BUNDLE__openmp-x86_64-pc-linux-gnu=readonly,exclude" "[[TEMPOBJ]]" "[[OUTOBJ]]"
258258

259259
// RUN: clang-offload-bundler -type=o -targets=host-%itanium_abi_triple,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -inputs=%t.o,%t.tgt1,%t.tgt2 -outputs=%t.bundle3.o
260260
// RUN: clang-offload-bundler -type=o -targets=host-%itanium_abi_triple,openmp-powerpc64le-ibm-linux-gnu,openmp-x86_64-pc-linux-gnu -outputs=%t.res.o,%t.res.tgt1,%t.res.tgt2 -inputs=%t.bundle3.o -unbundle
261-
// RUN: diff %t.o %t.res.o
261+
// RUN: diff %t.bundle3.o %t.res.o
262262
// RUN: diff %t.tgt1 %t.res.tgt1
263263
// RUN: diff %t.tgt2 %t.res.tgt2
264264
// RUN: clang-offload-bundler -type=o -targets=openmp-powerpc64le-ibm-linux-gnu,host-%itanium_abi_triple,openmp-x86_64-pc-linux-gnu -outputs=%t.res.tgt1,%t.res.o,%t.res.tgt2 -inputs=%t.bundle3.o -unbundle
265-
// RUN: diff %t.o %t.res.o
265+
// RUN: diff %t.bundle3.o %t.res.o
266266
// RUN: diff %t.tgt1 %t.res.tgt1
267267
// RUN: diff %t.tgt2 %t.res.tgt2
268268
// RUN: clang-offload-bundler -type=o -targets=openmp-powerpc64le-ibm-linux-gnu -outputs=%t.res.tgt1 -inputs=%t.bundle3.o -unbundle

clang/tools/clang-offload-bundler/ClangOffloadBundler.cpp

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
#include "llvm/Support/Error.h"
3131
#include "llvm/Support/ErrorOr.h"
3232
#include "llvm/Support/FileSystem.h"
33-
#include "llvm/Support/FileUtilities.h"
3433
#include "llvm/Support/MemoryBuffer.h"
3534
#include "llvm/Support/Path.h"
3635
#include "llvm/Support/Program.h"
@@ -365,6 +364,41 @@ class BinaryFileHandler final : public FileHandler {
365364
}
366365
};
367366

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+
368402
/// Handler for object files. The bundles are organized by sections with a
369403
/// designated name.
370404
///
@@ -433,11 +467,16 @@ class ObjectFileHandler final : public FileHandler {
433467
Error ReadBundleEnd(MemoryBuffer &Input) final { return Error::success(); }
434468

435469
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());
439478

440-
OS.write(Content->data(), Content->size());
479+
OS.write(Content.data(), Content.size());
441480
return Error::success();
442481
}
443482

@@ -486,22 +525,37 @@ class ObjectFileHandler final : public FileHandler {
486525
// to pass down to llvm-objcopy.
487526
OS.close();
488527

528+
// Temporary files that need to be removed.
529+
TempFileHandlerRAII TempFiles;
530+
489531
// Create an intermediate temporary file to save object after the first
490532
// 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;
496537

497538
// Compose llvm-objcopy command line for add target objects' sections.
498539
BumpPtrAllocator Alloc;
499540
StringSaver SS{Alloc};
500541
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+
502555
ObjcopyArgs.push_back(SS.save(Twine("--add-section=") +
503556
OFFLOAD_BUNDLER_MAGIC_STR + TargetNames[I] +
504-
"=" + InputFileNames[I]));
557+
"=" + InputFile));
558+
}
505559
ObjcopyArgs.push_back(InputFileNames[HostInputIndex]);
506560
ObjcopyArgs.push_back(IntermediateObj);
507561

0 commit comments

Comments
 (0)