// 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.
//
/// 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)
((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;
/// 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()) {
!(*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.
/// 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;
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();