aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/Target/X86
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2013-11-21 23:09:07 +0000
committerDimitry Andric <dim@FreeBSD.org>2013-11-21 23:09:07 +0000
commit711f10ae9f494401fa5b23f75dafc4e806e7e48e (patch)
treecce6e563cf584684a353855162fb2c5ac41a68e2 /contrib/llvm/lib/Target/X86
parent646c5b4840f4d31cf856f513b1e618d066a13058 (diff)
downloadsrc-711f10ae9f494401fa5b23f75dafc4e806e7e48e.tar.gz
src-711f10ae9f494401fa5b23f75dafc4e806e7e48e.zip
Pull in r195318 from upstream llvm trunk:
The basic problem is that some mainstream programs cannot deal with the way clang optimizes tail calls, as in this example: int foo(void); int bar(void) { return foo(); } where the call is transformed to: calll .L0$pb .L0$pb: popl %eax .Ltmp0: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp0-.L0$pb), %eax movl foo@GOT(%eax), %eax popl %ebp jmpl *%eax # TAILCALL However, the GOT references must all be resolved at dlopen() time, and so this approach cannot be used with lazy dynamic linking (e.g. using RTLD_LAZY), which usually populates the PLT with stubs that perform the actual resolving. This patch changes X86TargetLowering::LowerCall() to skip tail call optimization, if the called function is a global or external symbol. This fixes problems with loading X.org driver modules, which could occur when X.org was compiled on i386 with tailcall optimization on, for which ports r312583 was committed as a workaround. After this change, the workaround can be removed. MFC after: 3 days
Notes
Notes: svn path=/head/; revision=258455
Diffstat (limited to 'contrib/llvm/lib/Target/X86')
-rw-r--r--contrib/llvm/lib/Target/X86/X86ISelLowering.cpp22
1 files changed, 8 insertions, 14 deletions
diff --git a/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp b/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp
index c3e69e04bbd2..1080925551ea 100644
--- a/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -2449,21 +2449,15 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
RegsToPass.push_back(std::make_pair(unsigned(X86::EBX),
DAG.getNode(X86ISD::GlobalBaseReg, DebugLoc(), getPointerTy())));
} else {
- // If we are tail calling and generating PIC/GOT style code load the
- // address of the callee into ECX. The value in ecx is used as target of
- // the tail jump. This is done to circumvent the ebx/callee-saved problem
- // for tail calls on PIC/GOT architectures. Normally we would just put the
- // address of GOT into ebx and then call target@PLT. But for tail calls
- // ebx would be restored (since ebx is callee saved) before jumping to the
- // target@PLT.
-
- // Note: The actual moving to ECX is done further down.
+ // If we are tail calling a global or external symbol in GOT pic mode, we
+ // cannot use a direct jump, since that would make lazy dynamic linking
+ // impossible (see PR15086). So pretend this is not a tail call, to
+ // prevent the optimization to a jump.
GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee);
- if (G && !G->getGlobal()->hasHiddenVisibility() &&
- !G->getGlobal()->hasProtectedVisibility())
- Callee = LowerGlobalAddress(Callee, DAG);
- else if (isa<ExternalSymbolSDNode>(Callee))
- Callee = LowerExternalSymbol(Callee, DAG);
+ if ((G && !G->getGlobal()->hasHiddenVisibility() &&
+ !G->getGlobal()->hasProtectedVisibility()) ||
+ isa<ExternalSymbolSDNode>(Callee))
+ isTailCall = false;
}
}