jhuber6 created this revision. jhuber6 added reviewers: jdoerfert, JonChesterfield, tra, yaxunl, tianshilei1992. Herald added a project: All. jhuber6 requested review of this revision. Herald added subscribers: cfe-commits, jplehr, sstefan1. Herald added a project: clang.
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. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D146326 Files: clang/test/Driver/linker-wrapper-libs.c clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
Index: clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp =================================================================== --- clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -1162,7 +1162,8 @@ /// 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 @@ ((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 @@ /// 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()) { @@ -1225,12 +1228,15 @@ // We will extract if it defines a currenlty undefined non-weak symbol. bool ResolvesStrongReference = (OldSym & Sym_Undefined) && !(OldSym & Sym_Weak) && + !(*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 +1256,18 @@ /// 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 +1342,9 @@ 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(); Index: clang/test/Driver/linker-wrapper-libs.c =================================================================== --- clang/test/Driver/linker-wrapper-libs.c +++ clang/test/Driver/linker-wrapper-libs.c @@ -64,6 +64,29 @@ // 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. //
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits