mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-04-12 23:37:33 +00:00
Check for the returns_twice attribute in callsFunctionThatReturnsTwice. This
fixes PR11038, but there are still some cleanups to be done. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141204 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
30c1ff234d
commit
11f1a8335e
@ -1267,6 +1267,15 @@ public:
|
||||
else removeAttribute(~0, Attribute::NoInline);
|
||||
}
|
||||
|
||||
/// @brief Return true if the call can return twice
|
||||
bool canReturnTwice() const {
|
||||
return paramHasAttr(~0, Attribute::ReturnsTwice);
|
||||
}
|
||||
void setCanReturnTwice(bool Value = true) {
|
||||
if (Value) addAttribute(~0, Attribute::ReturnsTwice);
|
||||
else removeAttribute(~0, Attribute::ReturnsTwice);
|
||||
}
|
||||
|
||||
/// @brief Determine if the call does not access memory.
|
||||
bool doesNotAccessMemory() const {
|
||||
return paramHasAttr(~0, Attribute::ReadNone);
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "llvm/LLVMContext.h"
|
||||
#include "llvm/CodeGen/ValueTypes.h"
|
||||
#include "llvm/Support/CallSite.h"
|
||||
#include "llvm/Support/InstIterator.h"
|
||||
#include "llvm/Support/LeakDetector.h"
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
#include "llvm/Support/StringPool.h"
|
||||
@ -416,7 +417,6 @@ bool Function::hasAddressTaken(const User* *PutOffender) const {
|
||||
/// FIXME: Remove after <rdar://problem/8031714> is fixed.
|
||||
/// FIXME: Is the above FIXME valid?
|
||||
bool Function::callsFunctionThatReturnsTwice() const {
|
||||
const Module *M = this->getParent();
|
||||
static const char *ReturnsTwiceFns[] = {
|
||||
"_setjmp",
|
||||
"setjmp",
|
||||
@ -428,16 +428,25 @@ bool Function::callsFunctionThatReturnsTwice() const {
|
||||
"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;
|
||||
for (const_inst_iterator I = inst_begin(this), E = inst_end(this); I != E;
|
||||
++I) {
|
||||
const CallInst* callInst = dyn_cast<CallInst>(&*I);
|
||||
if (!callInst)
|
||||
continue;
|
||||
if (callInst->canReturnTwice())
|
||||
return true;
|
||||
|
||||
// check for known function names.
|
||||
// FIXME: move this to clang.
|
||||
Function *F = callInst->getCalledFunction();
|
||||
if (!F)
|
||||
continue;
|
||||
StringRef Name = F->getName();
|
||||
for (unsigned J = 0; J < array_lengthof(ReturnsTwiceFns); ++J) {
|
||||
if (Name == ReturnsTwiceFns[J])
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -1,16 +1,29 @@
|
||||
; RUN: opt < %s -tailcallelim -S | FileCheck %s
|
||||
|
||||
; Test that we don't tail call in a functions that calls setjmp.
|
||||
; Test that we don't tail call in a functions that calls returns_twice
|
||||
; functions.
|
||||
|
||||
declare void @bar()
|
||||
|
||||
; CHECK: foo1
|
||||
; CHECK-NOT: tail call void @bar()
|
||||
|
||||
define void @foo(i32* %x) {
|
||||
define void @foo1(i32* %x) {
|
||||
bb:
|
||||
%tmp75 = tail call i32 @setjmp(i32* %x)
|
||||
call void @bar()
|
||||
ret void
|
||||
}
|
||||
|
||||
declare i32 @setjmp(i32*) returns_twice
|
||||
declare i32 @setjmp(i32*)
|
||||
|
||||
declare void @bar()
|
||||
; CHECK: foo2
|
||||
; CHECK-NOT: tail call void @bar()
|
||||
|
||||
define void @foo2(i32* %x) {
|
||||
bb:
|
||||
%tmp75 = tail call i32 @zed2(i32* %x)
|
||||
call void @bar()
|
||||
ret void
|
||||
}
|
||||
declare i32 @zed2(i32*) returns_twice
|
||||
|
Loading…
x
Reference in New Issue
Block a user