Skip to content

[ClangOffloadBundler] fix unbundling archive #84195

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions clang/lib/Driver/OffloadBundler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,8 @@ class ObjectFileHandler final : public FileHandler {
// Copy fat object contents to the output when extracting host bundle.
std::string ModifiedContent;
if (Content.size() == 1u && Content.front() == 0) {
auto HostBundleOrErr = getHostBundle();
auto HostBundleOrErr = getHostBundle(
StringRef(Input.getBufferStart(), Input.getBufferSize()));
if (!HostBundleOrErr)
return HostBundleOrErr.takeError();

Expand Down Expand Up @@ -700,7 +701,7 @@ class ObjectFileHandler final : public FileHandler {
return Error::success();
}

Expected<std::string> getHostBundle() {
Expected<std::string> getHostBundle(StringRef Input) {
TempFileHandlerRAII TempFiles;

auto ModifiedObjPathOrErr = TempFiles.Create(std::nullopt);
Expand All @@ -715,7 +716,24 @@ class ObjectFileHandler final : public FileHandler {
ObjcopyArgs.push_back("--regex");
ObjcopyArgs.push_back("--remove-section=__CLANG_OFFLOAD_BUNDLE__.*");
ObjcopyArgs.push_back("--");
ObjcopyArgs.push_back(BundlerConfig.InputFileNames.front());

StringRef ObjcopyInputFileName;
// When unbundling an archive, the content of each object file in the
// archive is passed to this function by parameter Input, which is different
// from the content of the original input archive file, therefore it needs
// to be saved to a temporary file before passed to llvm-objcopy. Otherwise,
// Input is the same as the content of the original input file, therefore
// temporary file is not needed.
if (StringRef(BundlerConfig.FilesType).starts_with("a")) {
auto InputFileOrErr =
TempFiles.Create(ArrayRef<char>(Input.data(), Input.size()));
if (!InputFileOrErr)
return InputFileOrErr.takeError();
ObjcopyInputFileName = *InputFileOrErr;
} else
ObjcopyInputFileName = BundlerConfig.InputFileNames.front();

ObjcopyArgs.push_back(ObjcopyInputFileName);
ObjcopyArgs.push_back(ModifiedObjPath);

if (Error Err = executeObjcopy(BundlerConfig.ObjcopyPath, ObjcopyArgs))
Expand Down Expand Up @@ -1628,10 +1646,8 @@ Error OffloadBundler::UnbundleArchive() {
while (!CodeObject.empty()) {
SmallVector<StringRef> CompatibleTargets;
auto CodeObjectInfo = OffloadTargetInfo(CodeObject, BundlerConfig);
if (CodeObjectInfo.hasHostKind()) {
// Do nothing, we don't extract host code yet.
} else if (getCompatibleOffloadTargets(CodeObjectInfo, CompatibleTargets,
BundlerConfig)) {
if (getCompatibleOffloadTargets(CodeObjectInfo, CompatibleTargets,
BundlerConfig)) {
std::string BundleData;
raw_string_ostream DataStream(BundleData);
if (Error Err = FileHandler->ReadBundle(DataStream, CodeObjectBuffer))
Expand Down
32 changes: 32 additions & 0 deletions clang/test/Driver/clang-offload-bundler.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@
// RUN: obj2yaml %t.o > %t.o.yaml
// RUN: %clang -O0 -target %itanium_abi_triple %s -emit-ast -o %t.ast

// RUN: echo 'void a() {}' >%t.a.cpp
// RUN: echo 'void b() {}' >%t.b.cpp
// RUN: %clang -target %itanium_abi_triple %t.a.cpp -c -o %t.a.o
// RUN: %clang -target %itanium_abi_triple %t.b.cpp -c -o %t.b.o
//
// Remove .llvm_addrsig section since its offset changes after llvm-objcopy
// removes clang-offload-bundler sections, therefore not good for comparison.
//
// RUN: llvm-objcopy --remove-section=.llvm_addrsig %t.a.o
// RUN: llvm-objcopy --remove-section=.llvm_addrsig %t.b.o
// RUN: obj2yaml %t.a.o > %t.a.yaml
// RUN: obj2yaml %t.b.o > %t.b.yaml

//
// Generate an empty file to help with the checks of empty files.
//
Expand Down Expand Up @@ -414,6 +427,25 @@
// HIP-AR-906-DAG: hip_bundle1-hip-amdgcn-amd-amdhsa--gfx906
// HIP-AR-906-DAG: hip_bundle2-hip-amdgcn-amd-amdhsa--gfx906

//
// Check unbundling archive for host target
//
// RUN: clang-offload-bundler -type=o -targets=host-%itanium_abi_triple,hip-amdgcn-amd-amdhsa--gfx900 \
// RUN: -input=%t.a.o -input=%t.tgt1 -output=%t.a.bundled.o
// RUN: clang-offload-bundler -type=o -targets=host-%itanium_abi_triple,hip-amdgcn-amd-amdhsa--gfx900 \
// RUN: -input=%t.b.o -input=%t.tgt1 -output=%t.b.bundled.o
// RUN: rm -f %t.bundled.a
// RUN: llvm-ar cr %t.bundled.a %t.a.bundled.o %t.b.bundled.o
// RUN: cp %t.bundled.a %t.bundled.a.bak
// RUN: clang-offload-bundler -unbundle --targets=host-%itanium_abi_triple -type=a -input=%t.bundled.a -output=%t.host.a
// RUN: rm -f *%itanium_abi_triple*.a.bundled.o *%itanium_abi_triple*.b.bundled.o
// RUN: llvm-ar -x %t.host.a
// RUN: diff %t.bundled.a %t.bundled.a.bak
// RUN: obj2yaml *%itanium_abi_triple*.a.bundled.o > %t.a.unbundled.yaml
// RUN: diff %t.a.unbundled.yaml %t.a.yaml
// RUN: obj2yaml *%itanium_abi_triple*.b.bundled.o > %t.b.unbundled.yaml
// RUN: diff %t.b.unbundled.yaml %t.b.yaml
//
// Check clang-offload-bundler reporting an error when trying to unbundle an archive but
// the input file is not an archive.
//
Expand Down