Skip to content

Commit f2e29b6

Browse files
committed
[LinkerWrapper] Fix resolution of weak symbols during LTO
Summary: Weak symbols are supposed to have the semantics that they can be overriden by a strong (i.e. global) definition. This wasn't being respected by the LTO pass because we simply used the first definition that was available. This patch fixes that logic by doing a first pass over the symbols to check for strong resolutions that could override a weak one. A lot of fake linker logic is ending up in the linker wrapper. If there were an option to handle this in `lld` it would be a lot cleaner, but unfortunately supporting NVPTX is a big restriction as their binaries require the `nvlink` tool.
1 parent 452fa6b commit f2e29b6

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,7 @@ Error linkBitcodeFiles(SmallVectorImpl<OffloadFile> &InputFiles,
595595
StringRef Arch = Args.getLastArgValue(OPT_arch_EQ);
596596

597597
SmallVector<OffloadFile, 4> BitcodeInputFiles;
598+
DenseSet<StringRef> StrongResolutions;
598599
DenseSet<StringRef> UsedInRegularObj;
599600
DenseSet<StringRef> UsedInSharedLib;
600601
BumpPtrAllocator Alloc;
@@ -608,6 +609,18 @@ Error linkBitcodeFiles(SmallVectorImpl<OffloadFile> &InputFiles,
608609
file_magic Type = identify_magic(Buffer.getBuffer());
609610
switch (Type) {
610611
case file_magic::bitcode: {
612+
Expected<IRSymtabFile> IRSymtabOrErr = readIRSymtab(Buffer);
613+
if (!IRSymtabOrErr)
614+
return IRSymtabOrErr.takeError();
615+
616+
// Check for any strong resolutions we need to preserve.
617+
for (unsigned I = 0; I != IRSymtabOrErr->Mods.size(); ++I) {
618+
for (const auto &Sym : IRSymtabOrErr->TheReader.module_symbols(I)) {
619+
if (!Sym.isFormatSpecific() && Sym.isGlobal() && !Sym.isWeak() &&
620+
!Sym.isUndefined())
621+
StrongResolutions.insert(Saver.save(Sym.Name));
622+
}
623+
}
611624
BitcodeInputFiles.emplace_back(std::move(File));
612625
continue;
613626
}
@@ -696,6 +709,7 @@ Error linkBitcodeFiles(SmallVectorImpl<OffloadFile> &InputFiles,
696709
// it is undefined or another definition has already been used.
697710
Res.Prevailing =
698711
!Sym.isUndefined() &&
712+
!(Sym.isWeak() && StrongResolutions.contains(Sym.getName())) &&
699713
PrevailingSymbols.insert(Saver.save(Sym.getName())).second;
700714

701715
// We need LTO to preseve the following global symbols:
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// RUN: %libomptarget-compile-generic -DA -c -o %t-a.o
2+
// RUN: %libomptarget-compile-generic -DB -c -o %t-b.o
3+
// RUN: %libomptarget-compile-generic %t-a.o %t-b.o && \
4+
// RUN: %libomptarget-run-generic | %fcheck-generic
5+
6+
#if defined(A)
7+
__attribute__((weak)) int x = 999;
8+
#pragma omp declare target to(x)
9+
#elif defined(B)
10+
int x = 42;
11+
#pragma omp declare target to(x)
12+
__attribute__((weak)) int y = 42;
13+
#pragma omp declare target to(y)
14+
#else
15+
16+
#include <stdio.h>
17+
18+
extern int x;
19+
#pragma omp declare target to(x)
20+
extern int y;
21+
#pragma omp declare target to(y)
22+
23+
int main() {
24+
x = 0;
25+
26+
#pragma omp target update from(x)
27+
#pragma omp target update from(y)
28+
29+
// CHECK: PASS
30+
if (x == 42 && y == 42)
31+
printf("PASS\n");
32+
}
33+
#endif

0 commit comments

Comments
 (0)