From: Joseph Huber Date: Fri, 17 Mar 2023 20:10:25 +0000 (-0500) Subject: [LinkerWrapper] Do not extract globals with no offloading language X-Git-Tag: upstream/17.0.6~13566 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b530e1af62be16ffb06285ddca27a413f5089b7e;p=platform%2Fupstream%2Fllvm.git [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 --- diff --git a/clang/test/Driver/linker-wrapper-libs.c b/clang/test/Driver/linker-wrapper-libs.c index ee05304..acb7c38 100644 --- a/clang/test/Driver/linker-wrapper-libs.c +++ b/clang/test/Driver/linker-wrapper-libs.c @@ -65,6 +65,29 @@ int bar() { return weak; } // 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. // // RUN: %clang -cc1 %s -triple nvptx64-nvidia-cuda -emit-llvm-bc -DWEAK -o %t.nvptx.weak.bc diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp index 63e4039..2d96e0a 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 getSymbolsFromBitcode(MemoryBufferRef Buffer, StringSaver &Saver, +Expected getSymbolsFromBitcode(MemoryBufferRef Buffer, OffloadKind Kind, + StringSaver &Saver, DenseMap &Syms) { Expected IRSymtabOrErr = readIRSymtab(Buffer); if (!IRSymtabOrErr) @@ -1182,9 +1183,10 @@ Expected 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 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 getSymbolsFromObject(const ObjectFile &Obj, StringSaver &Saver, +Expected getSymbolsFromObject(const ObjectFile &Obj, OffloadKind Kind, + StringSaver &Saver, DenseMap &Syms) { bool ShouldExtract = false; for (SymbolRef Sym : Obj.symbols()) { @@ -1228,9 +1231,11 @@ Expected 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 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 getSymbols(StringRef Image, StringSaver &Saver, +Expected getSymbols(StringRef Image, OffloadKind Kind, StringSaver &Saver, DenseMap &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> 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> getDeviceInput(const ArgList &Args) { if (IsArchive && !WholeArchive && !Syms.count(Binary)) continue; - Expected ExtractOrErr = - getSymbols(Binary.getBinary()->getImage(), Saver, Syms[Binary]); + Expected ExtractOrErr = getSymbols( + Binary.getBinary()->getImage(), + Binary.getBinary()->getOffloadKind(), Saver, Syms[Binary]); if (!ExtractOrErr) return ExtractOrErr.takeError();