[clang] b530e1a - [LinkerWrapper] Do not extract globals with no offloading language
Joseph Huber via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 27 09:38:35 PDT 2023
Author: Joseph Huber
Date: 2023-03-27T11:38:27-05:00
New Revision: b530e1af62be16ffb06285ddca27a413f5089b7e
URL: https://github.com/llvm/llvm-project/commit/b530e1af62be16ffb06285ddca27a413f5089b7e
DIFF: https://github.com/llvm/llvm-project/commit/b530e1af62be16ffb06285ddca27a413f5089b7e.diff
LOG: [LinkerWrapper] Do not extract globals with no offloading language
The linker wrapper needs to reinvent its own special static library
handling for static libraries containing fatbinaries. This is primarily
because offloading languages expect certain global symbols to be visible
to the host so we must consider them used symbols. However we should be
able to remove this requirement if we are linking in "freestanding" code
that was not created by an offloading language.
The motivation for this is to support the work-in-progress `libc` for
GPUs. It is provided as a static library with no offloading language
set. This logic will let us only import used `libc` symbols always.
Reviewed By: yaxunl
Differential Revision: https://reviews.llvm.org/D146326
Added:
Modified:
clang/test/Driver/linker-wrapper-libs.c
clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
Removed:
################################################################################
diff --git a/clang/test/Driver/linker-wrapper-libs.c b/clang/test/Driver/linker-wrapper-libs.c
index ee05304b7f1a2..acb7c38165d04 100644
--- a/clang/test/Driver/linker-wrapper-libs.c
+++ b/clang/test/Driver/linker-wrapper-libs.c
@@ -64,6 +64,29 @@ int bar() { return weak; }
// LIBRARY-GLOBAL: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o
// LIBRARY-GLOBAL: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.s {{.*}}.o
+//
+// Check that we do not extract a global symbol if the source file was not
+// created by an offloading language that expects there to be a host version of
+// the symbol.
+//
+// RUN: %clang -cc1 %s -triple nvptx64-nvidia-cuda -emit-llvm-bc -DGLOBAL -o %t.nvptx.global.bc
+// RUN: %clang -cc1 %s -triple amdgcn-amd-amdhsa -emit-llvm-bc -DGLOBAL -o %t.amdgpu.global.bc
+// RUN: clang-offload-packager -o %t-lib.out \
+// RUN: --image=file=%t.nvptx.global.bc,triple=nvptx64-nvidia-cuda,arch=sm_70 \
+// RUN: --image=file=%t.amdgpu.global.bc,triple=amdgcn-amd-amdhsa,arch=gfx1030
+// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t-lib.out
+// RUN: llvm-ar rcs %t.a %t.o
+// RUN: clang-offload-packager -o %t.out \
+// RUN: --image=file=%t.elf.o,kind=openmp,triple=nvptx64-nvidia-cuda,arch=sm_70 \
+// RUN: --image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx1030
+// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o -fembed-offload-object=%t.out
+// RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \
+// RUN: --linker-path=/usr/bin/ld -- %t.o %t.a -o a.out 2>&1 \
+// RUN: | FileCheck %s --check-prefix=LIBRARY-GLOBAL-NONE
+
+// LIBRARY-GLOBAL-NONE-NOT: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o
+// LIBRARY-GLOBAL-NONE-NOT: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.s {{.*}}.o
+
//
// Check that we do not extract an external weak symbol.
//
diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
index 63e403964a738..2d96e0a344e11 100644
--- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -1162,7 +1162,8 @@ enum Symbol : uint32_t {
/// Scan the symbols from a BitcodeFile \p Buffer and record if we need to
/// extract any symbols from it.
-Expected<bool> getSymbolsFromBitcode(MemoryBufferRef Buffer, StringSaver &Saver,
+Expected<bool> getSymbolsFromBitcode(MemoryBufferRef Buffer, OffloadKind Kind,
+ StringSaver &Saver,
DenseMap<StringRef, Symbol> &Syms) {
Expected<IRSymtabFile> IRSymtabOrErr = readIRSymtab(Buffer);
if (!IRSymtabOrErr)
@@ -1182,9 +1183,10 @@ Expected<bool> getSymbolsFromBitcode(MemoryBufferRef Buffer, StringSaver &Saver,
((OldSym & Sym_Undefined && !(OldSym & Sym_Weak)) &&
!Sym.isUndefined());
// We will extract if it defines a new global symbol visible to the host.
+ // This is only necessary for code targeting an offloading language.
bool NewGlobalSymbol =
((NewSymbol || (OldSym & Sym_Undefined)) && !Sym.isUndefined() &&
- !Sym.canBeOmittedFromSymbolTable() &&
+ !Sym.canBeOmittedFromSymbolTable() && Kind != object::OFK_None &&
(Sym.getVisibility() != GlobalValue::HiddenVisibility));
ShouldExtract |= ResolvesStrongReference | NewGlobalSymbol;
@@ -1203,7 +1205,8 @@ Expected<bool> getSymbolsFromBitcode(MemoryBufferRef Buffer, StringSaver &Saver,
/// Scan the symbols from an ObjectFile \p Obj and record if we need to extract
/// any symbols from it.
-Expected<bool> getSymbolsFromObject(const ObjectFile &Obj, StringSaver &Saver,
+Expected<bool> getSymbolsFromObject(const ObjectFile &Obj, OffloadKind Kind,
+ StringSaver &Saver,
DenseMap<StringRef, Symbol> &Syms) {
bool ShouldExtract = false;
for (SymbolRef Sym : Obj.symbols()) {
@@ -1228,9 +1231,11 @@ Expected<bool> getSymbolsFromObject(const ObjectFile &Obj, StringSaver &Saver,
!(*FlagsOrErr & SymbolRef::SF_Undefined);
// We will extract if it defines a new global symbol visible to the host.
- bool NewGlobalSymbol = ((NewSymbol || (OldSym & Sym_Undefined)) &&
- !(*FlagsOrErr & SymbolRef::SF_Undefined) &&
- !(*FlagsOrErr & SymbolRef::SF_Hidden));
+ // This is only necessary for code targeting an offloading language.
+ bool NewGlobalSymbol =
+ ((NewSymbol || (OldSym & Sym_Undefined)) &&
+ !(*FlagsOrErr & SymbolRef::SF_Undefined) && Kind != object::OFK_None &&
+ !(*FlagsOrErr & SymbolRef::SF_Hidden));
ShouldExtract |= ResolvesStrongReference | NewGlobalSymbol;
// Update this symbol in the "table" with the new information.
@@ -1250,18 +1255,18 @@ Expected<bool> getSymbolsFromObject(const ObjectFile &Obj, StringSaver &Saver,
/// 1) It defines an undefined symbol in a regular object filie.
/// 2) It defines a global symbol without hidden visibility that has not
/// yet been defined.
-Expected<bool> getSymbols(StringRef Image, StringSaver &Saver,
+Expected<bool> getSymbols(StringRef Image, OffloadKind Kind, StringSaver &Saver,
DenseMap<StringRef, Symbol> &Syms) {
MemoryBufferRef Buffer = MemoryBufferRef(Image, "");
switch (identify_magic(Image)) {
case file_magic::bitcode:
- return getSymbolsFromBitcode(Buffer, Saver, Syms);
+ return getSymbolsFromBitcode(Buffer, Kind, Saver, Syms);
case file_magic::elf_relocatable: {
Expected<std::unique_ptr<ObjectFile>> ObjFile =
ObjectFile::createObjectFile(Buffer);
if (!ObjFile)
return ObjFile.takeError();
- return getSymbolsFromObject(**ObjFile, Saver, Syms);
+ return getSymbolsFromObject(**ObjFile, Kind, Saver, Syms);
}
default:
return false;
@@ -1336,8 +1341,9 @@ Expected<SmallVector<OffloadFile>> getDeviceInput(const ArgList &Args) {
if (IsArchive && !WholeArchive && !Syms.count(Binary))
continue;
- Expected<bool> ExtractOrErr =
- getSymbols(Binary.getBinary()->getImage(), Saver, Syms[Binary]);
+ Expected<bool> ExtractOrErr = getSymbols(
+ Binary.getBinary()->getImage(),
+ Binary.getBinary()->getOffloadKind(), Saver, Syms[Binary]);
if (!ExtractOrErr)
return ExtractOrErr.takeError();
More information about the cfe-commits
mailing list