diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2011-05-16 03:05:33 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2011-05-16 03:05:33 +0000 |
commit | 0e00c6c561181be7e9cc75ad2fee9cd4cbbfca1e (patch) | |
tree | ce64246a87e40887e6b6a022317abfec99e024d1 /lib/VMCore | |
parent | baaa3201681d58434a54f9cedfd600c248dc10e9 (diff) | |
download | external_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.cpp | 33 |
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 |