[llvm] bc56097 - [GlobalValue] Make dso_local function work with comdat nodeduplicate
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 13 16:37:18 PST 2022
Author: Fangrui Song
Date: 2022-01-13T16:37:14-08:00
New Revision: bc56097817bec3446edd9f06e2d78eab95033027
URL: https://github.com/llvm/llvm-project/commit/bc56097817bec3446edd9f06e2d78eab95033027
DIFF: https://github.com/llvm/llvm-project/commit/bc56097817bec3446edd9f06e2d78eab95033027.diff
LOG: [GlobalValue] Make dso_local function work with comdat nodeduplicate
This fixes -fno-semantic-interposition -fsanitize-coverage incompatibility.
-fPIC -fno-semantic-interposition may add dso_local to an external linkage
function. -fsanitize-coverage instrumentation does not clear dso_local when
adding comdat nodeduplicate. This causes a compatibility issue: the function
symbol may be referenced by a PC-relative relocation without using the local
alias. In -shared mode, ld will report a relocation error.
The fix is to either clear dso_local when adding comdat nodeduplicate, or
supporting comdat nodeduplicate. The latter is more appropriate, because a
comdat nodeduplicate is like not using comdat.
Note: The comdat condition was originally added by D77429 to not use local alias
for a hidden external linkage function in a deduplicate comdat. The condition
has been unused since the code was refactored to only use local alias for
default visibility symbols.
Note: `canBenefitFromLocalAlias` is used by clang/lib/CodeGen/CodeGenModule.cpp
and we don't want to add dso_local to default visibility external linkage comdat any
(clang/test/CodeGenCUDA/usual-deallocators.cu).
Differential Revision: https://reviews.llvm.org/D117190
Added:
Modified:
llvm/lib/IR/Globals.cpp
llvm/test/CodeGen/X86/linux-preemption.ll
Removed:
################################################################################
diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp
index 99affa8a84e6d..c832499dde060 100644
--- a/llvm/lib/IR/Globals.cpp
+++ b/llvm/lib/IR/Globals.cpp
@@ -105,10 +105,15 @@ bool GlobalValue::isInterposable() const {
}
bool GlobalValue::canBenefitFromLocalAlias() const {
- // See AsmPrinter::getSymbolPreferLocal().
+ // See AsmPrinter::getSymbolPreferLocal(). For a deduplicate comdat kind,
+ // references to a discarded local symbol from outside the group are not
+ // allowed, so avoid the local alias.
+ auto isDeduplicateComdat = [](const Comdat *C) {
+ return C && C->getSelectionKind() != Comdat::NoDeduplicate;
+ };
return hasDefaultVisibility() &&
GlobalObject::isExternalLinkage(getLinkage()) && !isDeclaration() &&
- !isa<GlobalIFunc>(this) && !hasComdat();
+ !isa<GlobalIFunc>(this) && !isDeduplicateComdat(getComdat());
}
unsigned GlobalValue::getAddressSpace() const {
diff --git a/llvm/test/CodeGen/X86/linux-preemption.ll b/llvm/test/CodeGen/X86/linux-preemption.ll
index eae14f98cf0da..ce2259992418b 100644
--- a/llvm/test/CodeGen/X86/linux-preemption.ll
+++ b/llvm/test/CodeGen/X86/linux-preemption.ll
@@ -252,6 +252,32 @@ define void()* @get_external_preemptable_function() {
; STATIC: movq external_preemptable_function at GOTPCREL(%rip), %rax
; CHECK32: movl external_preemptable_function at GOT(%eax), %eax
+$comdat_nodeduplicate_local = comdat nodeduplicate
+$comdat_nodeduplicate_preemptable = comdat nodeduplicate
+$comdat_any_local = comdat any
+
+;; -fpic -fno-semantic-interposition may add dso_local. Some instrumentation
+;; may add comdat nodeduplicate. We should use local aliases to make the symbol
+;; non-preemptible in the linker.
+define dso_local i8* @comdat_nodeduplicate_local() comdat {
+ ret i8* bitcast (i8* ()* @comdat_nodeduplicate_local to i8*)
+}
+; CHECK: leaq .Lcomdat_nodeduplicate_local$local(%rip), %rax
+; STATIC: movl $comdat_nodeduplicate_local, %eax
+
+define dso_preemptable i8* @comdat_nodeduplicate_preemptable() comdat {
+ ret i8* bitcast (i8* ()* @comdat_nodeduplicate_preemptable to i8*)
+}
+; CHECK: movq comdat_nodeduplicate_preemptable at GOTPCREL(%rip), %rax
+; STATIC: movq comdat_nodeduplicate_preemptable at GOTPCREL(%rip), %rax
+
+;; Check the behavior for the invalid construct.
+define dso_local i8* @comdat_any_local() comdat {
+ ret i8* bitcast (i8* ()* @comdat_any_local to i8*)
+}
+; CHECK: leaq comdat_any_local(%rip), %rax
+; STATIC: movl $comdat_any_local, %eax
+
!llvm.module.flags = !{!0}
!0 = !{i32 7, !"PIC Level", i32 2}
More information about the llvm-commits
mailing list