[clang] [llvm] [arm] using got indirection not pc-relative for weak symbol (PR #190885)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 7 19:07:42 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-driver
Author: Austin (Zhenhang1213)
<details>
<summary>Changes</summary>
Fixes https://github.com/llvm/llvm-project/issues/183916
---
Full diff: https://github.com/llvm/llvm-project/pull/190885.diff
2 Files Affected:
- (added) clang/test/Driver/weak-symbol-pic.c (+17)
- (modified) llvm/lib/Target/TargetMachine.cpp (+9)
``````````diff
diff --git a/clang/test/Driver/weak-symbol-pic.c b/clang/test/Driver/weak-symbol-pic.c
new file mode 100644
index 0000000000000..44b8a55f0f0de
--- /dev/null
+++ b/clang/test/Driver/weak-symbol-pic.c
@@ -0,0 +1,17 @@
+// RUN: %clang -fpic -S -target arm-linux-gnueabihf -o - %s | FileCheck %s
+// RUN: %clang -fpic -S -target armeb-linux-gnueabihf -o - %s | FileCheck %s
+
+// Test that weak symbols use GOT relocations in PIC mode on ARM.
+// This matches GCC behavior where weak symbols require GOT because they
+// can be preempted at runtime.
+
+// CHECK: xxx(GOT_PREL)
+
+void __attribute__((__weak__)) xxx(void);
+
+void call_func(void (*f)(void));
+
+int main() {
+ call_func(xxx);
+ return 0;
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/TargetMachine.cpp b/llvm/lib/Target/TargetMachine.cpp
index 9243cdad43e1e..71602b2a262cd 100644
--- a/llvm/lib/Target/TargetMachine.cpp
+++ b/llvm/lib/Target/TargetMachine.cpp
@@ -212,6 +212,14 @@ bool TargetMachine::shouldAssumeDSOLocal(const GlobalValue *GV) const {
if (!GV)
return false;
+ // Weak symbols can be preempted at runtime, so don't assume they're DSO
+ // local. This is important for PIC code where we need GOT relocations for
+ // weak symbols. Only apply this fix for ARM targets to match GCC behavior.
+ if ((GV->hasWeakLinkage() || GV->hasExternalWeakLinkage()) &&
+ (TT.getArch() == Triple::arm || TT.getArch() == Triple::armeb ||
+ TT.getArch() == Triple::thumb || TT.getArch() == Triple::thumbeb))
+ return false;
+
// If the IR producer requested that this GV be treated as dso local, obey.
if (GV->isDSOLocal())
return true;
@@ -251,6 +259,7 @@ bool TargetMachine::shouldAssumeDSOLocal(const GlobalValue *GV) const {
assert(TT.isOSBinFormatELF() || TT.isOSBinFormatWasm() ||
TT.isOSBinFormatXCOFF());
+
return false;
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/190885
More information about the cfe-commits
mailing list