mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-18 09:27:27 +00:00
[ARM,AArch64] Do not tail-call to an externally-defined function with weak linkage
Externally-defined functions with weak linkage should not be tail-called on ARM or AArch64, as the AAELF spec requires normal calls to undefined weak functions to be replaced with a NOP or jump to the next instruction. The behaviour of branch instructions in this situation (as used for tail calls) is implementation-defined, so we cannot rely on the linker replacing the tail call with a return. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@215890 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9735ccb7ea
commit
802d420792
@ -2016,6 +2016,19 @@ bool AArch64TargetLowering::isEligibleForTailCallOptimization(
|
||||
return false;
|
||||
}
|
||||
|
||||
// Externally-defined functions with weak linkage should not be
|
||||
// tail-called on AArch64 when the OS does not support dynamic
|
||||
// pre-emption of symbols, as the AAELF spec requires normal calls
|
||||
// to undefined weak functions to be replaced with a NOP or jump to the
|
||||
// next instruction. The behaviour of branch instructions in this
|
||||
// situation (as used for tail calls) is implementation-defined, so we
|
||||
// cannot rely on the linker replacing the tail call with a return.
|
||||
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
|
||||
const GlobalValue *GV = G->getGlobal();
|
||||
if (GV->hasExternalWeakLinkage())
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now we search for cases where we can use a tail call without changing the
|
||||
// ABI. Sibcall is used in some places (particularly gcc) to refer to this
|
||||
// concept.
|
||||
|
@ -1997,6 +1997,19 @@ ARMTargetLowering::IsEligibleForTailCallOptimization(SDValue Callee,
|
||||
if (Subtarget->isThumb1Only())
|
||||
return false;
|
||||
|
||||
// Externally-defined functions with weak linkage should not be
|
||||
// tail-called on ARM when the OS does not support dynamic
|
||||
// pre-emption of symbols, as the AAELF spec requires normal calls
|
||||
// to undefined weak functions to be replaced with a NOP or jump to the
|
||||
// next instruction. The behaviour of branch instructions in this
|
||||
// situation (as used for tail calls) is implementation-defined, so we
|
||||
// cannot rely on the linker replacing the tail call with a return.
|
||||
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
|
||||
const GlobalValue *GV = G->getGlobal();
|
||||
if (GV->hasExternalWeakLinkage())
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the calling conventions do not match, then we'd better make sure the
|
||||
// results are returned in the same way as what the caller expects.
|
||||
if (!CCMatch) {
|
||||
|
@ -3,6 +3,7 @@
|
||||
declare fastcc void @callee_stack0()
|
||||
declare fastcc void @callee_stack8([8 x i32], i64)
|
||||
declare fastcc void @callee_stack16([8 x i32], i64, i64)
|
||||
declare extern_weak fastcc void @callee_weak()
|
||||
|
||||
define fastcc void @caller_to0_from0() nounwind {
|
||||
; CHECK-LABEL: caller_to0_from0:
|
||||
@ -92,3 +93,13 @@ define fastcc void @caller_to16_from16([8 x i32], i64 %a, i64 %b) {
|
||||
; CHECK-NEXT: add sp, sp, #16
|
||||
; CHECK-NEXT: b callee_stack16
|
||||
}
|
||||
|
||||
|
||||
; Weakly-referenced extern functions cannot be tail-called, as AAELF does
|
||||
; not define the behaviour of branch instructions to undefined weak symbols.
|
||||
define fastcc void @caller_weak() {
|
||||
; CHECK-LABEL: caller_weak:
|
||||
; CHECK: bl callee_weak
|
||||
tail call void @callee_weak()
|
||||
ret void
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
; RUN: | FileCheck %s -check-prefix CHECK-NO-TAIL
|
||||
|
||||
declare i32 @callee(i32 %i)
|
||||
declare extern_weak fastcc void @callee_weak()
|
||||
|
||||
define i32 @caller(i32 %i) {
|
||||
entry:
|
||||
@ -19,3 +20,12 @@ entry:
|
||||
; CHECK-NO-TAIL: pop {lr}
|
||||
; CHECK-NO-TAIL: bx lr
|
||||
|
||||
|
||||
; Weakly-referenced extern functions cannot be tail-called, as AAELF does
|
||||
; not define the behaviour of branch instructions to undefined weak symbols.
|
||||
define fastcc void @caller_weak() {
|
||||
; CHECK-LABEL: caller_weak:
|
||||
; CHECK: bl callee_weak
|
||||
tail call void @callee_weak()
|
||||
ret void
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user