diff --git a/clang/test/Driver/linker-wrapper-libs.c b/clang/test/Driver/linker-wrapper-libs.c index acb7c38165d04..2073092bdbcf9 100644 --- a/clang/test/Driver/linker-wrapper-libs.c +++ b/clang/test/Driver/linker-wrapper-libs.c @@ -12,6 +12,9 @@ int __attribute__((visibility("protected"))) global; int __attribute__((visibility("hidden"))) weak; #elif defined(HIDDEN) int __attribute__((visibility("hidden"))) hidden; +#elif defined(UNDEFINED) +extern int sym; +int baz() { return sym; } #else extern int sym; @@ -26,7 +29,11 @@ int bar() { return weak; } // // RUN: %clang -cc1 %s -triple nvptx64-nvidia-cuda -emit-llvm-bc -DRESOLVES -o %t.nvptx.resolves.bc // RUN: %clang -cc1 %s -triple amdgcn-amd-amdhsa -emit-llvm-bc -DRESOLVES -o %t.amdgpu.resolves.bc +// RUN: %clang -cc1 %s -triple nvptx64-nvidia-cuda -emit-llvm-bc -DUNDEFINED -o %t.nvptx.undefined.bc +// RUN: %clang -cc1 %s -triple amdgcn-amd-amdhsa -emit-llvm-bc -DUNDEFINED -o %t.amdgpu.undefined.bc // RUN: clang-offload-packager -o %t-lib.out \ +// RUN: --image=file=%t.nvptx.undefined.bc,kind=openmp,triple=nvptx64-nvidia-cuda,arch=sm_70 \ +// RUN: --image=file=%t.amdgpu.undefined.bc,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx1030 \ // RUN: --image=file=%t.nvptx.resolves.bc,kind=openmp,triple=nvptx64-nvidia-cuda,arch=sm_70 \ // RUN: --image=file=%t.amdgpu.resolves.bc,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-lib.out diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp index 2d96e0a344e11..0af0f2e371b18 100644 --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -1163,20 +1163,21 @@ 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, OffloadKind Kind, - StringSaver &Saver, + bool IsArchive, StringSaver &Saver, DenseMap &Syms) { Expected IRSymtabOrErr = readIRSymtab(Buffer); if (!IRSymtabOrErr) return IRSymtabOrErr.takeError(); - bool ShouldExtract = false; + bool ShouldExtract = !IsArchive; + DenseMap TmpSyms; for (unsigned I = 0; I != IRSymtabOrErr->Mods.size(); ++I) { for (const auto &Sym : IRSymtabOrErr->TheReader.module_symbols(I)) { if (Sym.isFormatSpecific() || !Sym.isGlobal()) continue; bool NewSymbol = Syms.count(Sym.getName()) == 0; - auto &OldSym = Syms[Saver.save(Sym.getName())]; + auto OldSym = NewSymbol ? Sym_None : Syms[Sym.getName()]; // We will extract if it defines a currenlty undefined non-weak symbol. bool ResolvesStrongReference = @@ -1192,23 +1193,31 @@ Expected getSymbolsFromBitcode(MemoryBufferRef Buffer, OffloadKind Kind, // Update this symbol in the "table" with the new information. if (OldSym & Sym_Undefined && !Sym.isUndefined()) - OldSym = static_cast(OldSym & ~Sym_Undefined); + TmpSyms[Saver.save(Sym.getName())] = + static_cast(OldSym & ~Sym_Undefined); if (Sym.isUndefined() && NewSymbol) - OldSym = static_cast(OldSym | Sym_Undefined); + TmpSyms[Saver.save(Sym.getName())] = + static_cast(OldSym | Sym_Undefined); if (Sym.isWeak()) - OldSym = static_cast(OldSym | Sym_Weak); + TmpSyms[Saver.save(Sym.getName())] = + static_cast(OldSym | Sym_Weak); } } + // If the file gets extracted we update the table with the new symbols. + if (ShouldExtract) + Syms.insert(std::begin(TmpSyms), std::end(TmpSyms)); + return ShouldExtract; } /// Scan the symbols from an ObjectFile \p Obj and record if we need to extract /// any symbols from it. Expected getSymbolsFromObject(const ObjectFile &Obj, OffloadKind Kind, - StringSaver &Saver, + bool IsArchive, StringSaver &Saver, DenseMap &Syms) { - bool ShouldExtract = false; + bool ShouldExtract = !IsArchive; + DenseMap TmpSyms; for (SymbolRef Sym : Obj.symbols()) { auto FlagsOrErr = Sym.getFlags(); if (!FlagsOrErr) @@ -1223,7 +1232,7 @@ Expected getSymbolsFromObject(const ObjectFile &Obj, OffloadKind Kind, return NameOrErr.takeError(); bool NewSymbol = Syms.count(*NameOrErr) == 0; - auto &OldSym = Syms[Saver.save(*NameOrErr)]; + auto OldSym = NewSymbol ? Sym_None : Syms[*NameOrErr]; // We will extract if it defines a currenlty undefined non-weak symbol. bool ResolvesStrongReference = (OldSym & Sym_Undefined) && @@ -1240,12 +1249,19 @@ Expected getSymbolsFromObject(const ObjectFile &Obj, OffloadKind Kind, // Update this symbol in the "table" with the new information. if (OldSym & Sym_Undefined && !(*FlagsOrErr & SymbolRef::SF_Undefined)) - OldSym = static_cast(OldSym & ~Sym_Undefined); + TmpSyms[Saver.save(*NameOrErr)] = + static_cast(OldSym & ~Sym_Undefined); if (*FlagsOrErr & SymbolRef::SF_Undefined && NewSymbol) - OldSym = static_cast(OldSym | Sym_Undefined); + TmpSyms[Saver.save(*NameOrErr)] = + static_cast(OldSym | Sym_Undefined); if (*FlagsOrErr & SymbolRef::SF_Weak) - OldSym = static_cast(OldSym | Sym_Weak); + TmpSyms[Saver.save(*NameOrErr)] = static_cast(OldSym | Sym_Weak); } + + // If the file gets extracted we update the table with the new symbols. + if (ShouldExtract) + Syms.insert(std::begin(TmpSyms), std::end(TmpSyms)); + return ShouldExtract; } @@ -1255,18 +1271,19 @@ Expected getSymbolsFromObject(const ObjectFile &Obj, OffloadKind Kind, /// 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, OffloadKind Kind, StringSaver &Saver, +Expected getSymbols(StringRef Image, OffloadKind Kind, bool IsArchive, + StringSaver &Saver, DenseMap &Syms) { MemoryBufferRef Buffer = MemoryBufferRef(Image, ""); switch (identify_magic(Image)) { case file_magic::bitcode: - return getSymbolsFromBitcode(Buffer, Kind, Saver, Syms); + return getSymbolsFromBitcode(Buffer, Kind, IsArchive, Saver, Syms); case file_magic::elf_relocatable: { Expected> ObjFile = ObjectFile::createObjectFile(Buffer); if (!ObjFile) return ObjFile.takeError(); - return getSymbolsFromObject(**ObjFile, Kind, Saver, Syms); + return getSymbolsFromObject(**ObjFile, Kind, IsArchive, Saver, Syms); } default: return false; @@ -1341,13 +1358,14 @@ Expected> getDeviceInput(const ArgList &Args) { if (IsArchive && !WholeArchive && !Syms.count(Binary)) continue; - Expected ExtractOrErr = getSymbols( - Binary.getBinary()->getImage(), - Binary.getBinary()->getOffloadKind(), Saver, Syms[Binary]); + Expected ExtractOrErr = + getSymbols(Binary.getBinary()->getImage(), + Binary.getBinary()->getOffloadKind(), IsArchive, Saver, + Syms[Binary]); if (!ExtractOrErr) return ExtractOrErr.takeError(); - Extracted = IsArchive && !WholeArchive && *ExtractOrErr; + Extracted = !WholeArchive && *ExtractOrErr; if (!IsArchive || WholeArchive || Extracted) InputFiles.emplace_back(std::move(Binary));