aboutsummaryrefslogtreecommitdiffstats
path: root/lib/VMCore
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2011-05-16 03:05:33 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2011-05-16 03:05:33 +0000
commit0e00c6c561181be7e9cc75ad2fee9cd4cbbfca1e (patch)
treece64246a87e40887e6b6a022317abfec99e024d1 /lib/VMCore
parentbaaa3201681d58434a54f9cedfd600c248dc10e9 (diff)
downloadexternal_llvm-0e00c6c561181be7e9cc75ad2fee9cd4cbbfca1e.zip
external_llvm-0e00c6c561181be7e9cc75ad2fee9cd4cbbfca1e.tar.gz
external_llvm-0e00c6c561181be7e9cc75ad2fee9cd4cbbfca1e.tar.bz2
Don't do tail calls in a function that call setjmp. The stack might be
corrupted when setjmp returns again. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@131399 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/VMCore')
-rw-r--r--lib/VMCore/Function.cpp33
1 files changed, 33 insertions, 0 deletions
diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp
index 013c458..ce2186f 100644
--- a/lib/VMCore/Function.cpp
+++ b/lib/VMCore/Function.cpp
@@ -24,6 +24,7 @@
#include "llvm/Support/Threading.h"
#include "SymbolTableListTraitsImpl.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
using namespace llvm;
@@ -406,4 +407,36 @@ bool Function::hasAddressTaken(const User* *PutOffender) const {
return false;
}
+/// callsFunctionThatReturnsTwice - Return true if the function has a call to
+/// setjmp or other function that gcc recognizes as "returning twice".
+///
+/// FIXME: Remove after <rdar://problem/8031714> is fixed.
+/// FIXME: Is the obove FIXME valid?
+bool Function::callsFunctionThatReturnsTwice() const {
+ const Module *M = this->getParent();
+ static const char *ReturnsTwiceFns[] = {
+ "_setjmp",
+ "setjmp",
+ "sigsetjmp",
+ "setjmp_syscall",
+ "savectx",
+ "qsetjmp",
+ "vfork",
+ "getcontext"
+ };
+
+ for (unsigned I = 0; I < array_lengthof(ReturnsTwiceFns); ++I)
+ if (const Function *Callee = M->getFunction(ReturnsTwiceFns[I])) {
+ if (!Callee->use_empty())
+ for (Value::const_use_iterator
+ I = Callee->use_begin(), E = Callee->use_end();
+ I != E; ++I)
+ if (const CallInst *CI = dyn_cast<CallInst>(*I))
+ if (CI->getParent()->getParent() == this)
+ return true;
+ }
+
+ return false;
+}
+
// vim: sw=2 ai