forked from OSchip/llvm-project
[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
This commit is contained in:
parent
0f500d3dae
commit
bc56097817
|
@ -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 {
|
||||
|
|
|
@ -252,6 +252,32 @@ define void()* @get_external_preemptable_function() {
|
|||
; STATIC: movq external_preemptable_function@GOTPCREL(%rip), %rax
|
||||
; CHECK32: movl external_preemptable_function@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@GOTPCREL(%rip), %rax
|
||||
; STATIC: movq comdat_nodeduplicate_preemptable@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}
|
||||
|
||||
|
|
Loading…
Reference in New Issue