forked from OSchip/llvm-project
[CodeGen] Teach SimplifyPersonality about the updated LandingPadInst
When uses of personality functions were moved from LandingPadInst to Function, we forgot to update SimplifyPersonality(). This patch corrects that. Note: SimplifyPersonality() is an optimization which replaces personality functions with the default C++ personality when possible. Without this update, some ObjC++ projects fail to link against C++ libraries (seeing as the exception ABI had effectively changed). rdar://problem/22155434 llvm-svn: 247421
This commit is contained in:
parent
9676db005e
commit
db609471ce
|
@ -229,6 +229,36 @@ static llvm::Constant *getOpaquePersonalityFn(CodeGenModule &CGM,
|
|||
return llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
|
||||
}
|
||||
|
||||
/// Check whether a landingpad instruction only uses C++ features.
|
||||
static bool LandingPadHasOnlyCXXUses(llvm::LandingPadInst *LPI) {
|
||||
for (unsigned I = 0, E = LPI->getNumClauses(); I != E; ++I) {
|
||||
// Look for something that would've been returned by the ObjC
|
||||
// runtime's GetEHType() method.
|
||||
llvm::Value *Val = LPI->getClause(I)->stripPointerCasts();
|
||||
if (LPI->isCatch(I)) {
|
||||
// Check if the catch value has the ObjC prefix.
|
||||
if (llvm::GlobalVariable *GV = dyn_cast<llvm::GlobalVariable>(Val))
|
||||
// ObjC EH selector entries are always global variables with
|
||||
// names starting like this.
|
||||
if (GV->getName().startswith("OBJC_EHTYPE"))
|
||||
return false;
|
||||
} else {
|
||||
// Check if any of the filter values have the ObjC prefix.
|
||||
llvm::Constant *CVal = cast<llvm::Constant>(Val);
|
||||
for (llvm::User::op_iterator
|
||||
II = CVal->op_begin(), IE = CVal->op_end(); II != IE; ++II) {
|
||||
if (llvm::GlobalVariable *GV =
|
||||
cast<llvm::GlobalVariable>((*II)->stripPointerCasts()))
|
||||
// ObjC EH selector entries are always global variables with
|
||||
// names starting like this.
|
||||
if (GV->getName().startswith("OBJC_EHTYPE"))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Check whether a personality function could reasonably be swapped
|
||||
/// for a C++ personality function.
|
||||
static bool PersonalityHasOnlyCXXUses(llvm::Constant *Fn) {
|
||||
|
@ -241,34 +271,14 @@ static bool PersonalityHasOnlyCXXUses(llvm::Constant *Fn) {
|
|||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, it has to be a landingpad instruction.
|
||||
llvm::LandingPadInst *LPI = dyn_cast<llvm::LandingPadInst>(U);
|
||||
if (!LPI) return false;
|
||||
// Otherwise it must be a function.
|
||||
llvm::Function *F = dyn_cast<llvm::Function>(U);
|
||||
if (!F) return false;
|
||||
|
||||
for (unsigned I = 0, E = LPI->getNumClauses(); I != E; ++I) {
|
||||
// Look for something that would've been returned by the ObjC
|
||||
// runtime's GetEHType() method.
|
||||
llvm::Value *Val = LPI->getClause(I)->stripPointerCasts();
|
||||
if (LPI->isCatch(I)) {
|
||||
// Check if the catch value has the ObjC prefix.
|
||||
if (llvm::GlobalVariable *GV = dyn_cast<llvm::GlobalVariable>(Val))
|
||||
// ObjC EH selector entries are always global variables with
|
||||
// names starting like this.
|
||||
if (GV->getName().startswith("OBJC_EHTYPE"))
|
||||
return false;
|
||||
} else {
|
||||
// Check if any of the filter values have the ObjC prefix.
|
||||
llvm::Constant *CVal = cast<llvm::Constant>(Val);
|
||||
for (llvm::User::op_iterator
|
||||
II = CVal->op_begin(), IE = CVal->op_end(); II != IE; ++II) {
|
||||
if (llvm::GlobalVariable *GV =
|
||||
cast<llvm::GlobalVariable>((*II)->stripPointerCasts()))
|
||||
// ObjC EH selector entries are always global variables with
|
||||
// names starting like this.
|
||||
if (GV->getName().startswith("OBJC_EHTYPE"))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (auto BB = F->begin(), E = F->end(); BB != E; ++BB) {
|
||||
if (BB->isLandingPad())
|
||||
if (!LandingPadHasOnlyCXXUses(BB->getLandingPadInst()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -emit-llvm -fcxx-exceptions -fexceptions -fobjc-exceptions -o - %s | FileCheck %s
|
||||
|
||||
// rdar://problem/22155434
|
||||
namespace test0 {
|
||||
void foo() {
|
||||
try {
|
||||
throw 0;
|
||||
} catch (...) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// CHECK: define void @_ZN5test03fooEv() #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -emit-llvm -fcxx-exceptions -fexceptions -fobjc-exceptions -o - %s | FileCheck %s
|
||||
|
||||
extern "C" {
|
||||
int __objc_personality_v0();
|
||||
}
|
||||
|
||||
void *abuse_personality_func() {
|
||||
return (void *)&__objc_personality_v0;
|
||||
}
|
||||
|
||||
void foo() {
|
||||
try {
|
||||
throw 0;
|
||||
} catch (...) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK: define void @_Z3foov() #1 personality i8* bitcast (i32 ()* @__objc_personality_v0 to i8*)
|
Loading…
Reference in New Issue