summaryrefslogtreecommitdiff
path: root/lib/CodeGen/DwarfEHPrepare.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-05-28 07:45:59 +0000
committerJohn McCall <rjmccall@apple.com>2011-05-28 07:45:59 +0000
commitd7c10862016939c9850cadfe5e1c35513c0adf28 (patch)
tree9c4361dee8c7f6f75c33e68bd4a8de1223e6f6d3 /lib/CodeGen/DwarfEHPrepare.cpp
parentbd0fa4c00d7870b1da36eac7b2181700381f2f96 (diff)
downloadllvm-d7c10862016939c9850cadfe5e1c35513c0adf28.tar.gz
llvm-d7c10862016939c9850cadfe5e1c35513c0adf28.tar.bz2
llvm-d7c10862016939c9850cadfe5e1c35513c0adf28.tar.xz
Implement and document the llvm.eh.resume intrinsic, which is
transformed by the inliner into a branch to the enclosing landing pad (when inlined through an invoke). If not so optimized, it is lowered DWARF EH preparation into a call to _Unwind_Resume (or _Unwind_SjLj_Resume as appropriate). Its chief advantage is that it takes both the exception value and the selector value as arguments, meaning that there is zero effort in recovering these; however, the frontend is required to pass these down, which is not actually particularly difficult. Also document the behavior of landing pads a bit better, and make it clearer that it's okay that personality functions don't always land at landing pads. This is just a fact of life. Don't write optimizations that rely on pushing things over an unwind edge. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@132253 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/DwarfEHPrepare.cpp')
-rw-r--r--lib/CodeGen/DwarfEHPrepare.cpp67
1 files changed, 42 insertions, 25 deletions
diff --git a/lib/CodeGen/DwarfEHPrepare.cpp b/lib/CodeGen/DwarfEHPrepare.cpp
index 34b1a396bb..6a53e69337 100644
--- a/lib/CodeGen/DwarfEHPrepare.cpp
+++ b/lib/CodeGen/DwarfEHPrepare.cpp
@@ -30,6 +30,7 @@ using namespace llvm;
STATISTIC(NumLandingPadsSplit, "Number of landing pads split");
STATISTIC(NumUnwindsLowered, "Number of unwind instructions lowered");
+STATISTIC(NumResumesLowered, "Number of eh.resume calls lowered");
STATISTIC(NumExceptionValuesMoved, "Number of eh.exception calls moved");
namespace {
@@ -63,7 +64,7 @@ namespace {
BBSet LandingPads;
bool NormalizeLandingPads();
- bool LowerUnwinds();
+ bool LowerUnwindsAndResumes();
bool MoveExceptionValueCalls();
Instruction *CreateExceptionValueCall(BasicBlock *BB);
@@ -480,20 +481,25 @@ bool DwarfEHPrepare::NormalizeLandingPads() {
/// rethrowing any previously caught exception. This will crash horribly
/// at runtime if there is no such exception: using unwind to throw a new
/// exception is currently not supported.
-bool DwarfEHPrepare::LowerUnwinds() {
- SmallVector<TerminatorInst*, 16> UnwindInsts;
-
- for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) {
- TerminatorInst *TI = I->getTerminator();
- if (isa<UnwindInst>(TI))
- UnwindInsts.push_back(TI);
+bool DwarfEHPrepare::LowerUnwindsAndResumes() {
+ SmallVector<Instruction*, 16> ResumeInsts;
+
+ for (Function::iterator fi = F->begin(), fe = F->end(); fi != fe; ++fi) {
+ for (BasicBlock::iterator bi = fi->begin(), be = fi->end(); bi != be; ++bi){
+ if (isa<UnwindInst>(bi))
+ ResumeInsts.push_back(bi);
+ else if (CallInst *call = dyn_cast<CallInst>(bi))
+ if (Function *fn = dyn_cast<Function>(call->getCalledValue()))
+ if (fn->getName() == "llvm.eh.resume")
+ ResumeInsts.push_back(bi);
+ }
}
- if (UnwindInsts.empty()) return false;
+ if (ResumeInsts.empty()) return false;
// Find the rewind function if we didn't already.
if (!RewindFunction) {
- LLVMContext &Ctx = UnwindInsts[0]->getContext();
+ LLVMContext &Ctx = ResumeInsts[0]->getContext();
std::vector<const Type*>
Params(1, Type::getInt8PtrTy(Ctx));
FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
@@ -504,24 +510,35 @@ bool DwarfEHPrepare::LowerUnwinds() {
bool Changed = false;
- for (SmallVectorImpl<TerminatorInst*>::iterator
- I = UnwindInsts.begin(), E = UnwindInsts.end(); I != E; ++I) {
- TerminatorInst *TI = *I;
+ for (SmallVectorImpl<Instruction*>::iterator
+ I = ResumeInsts.begin(), E = ResumeInsts.end(); I != E; ++I) {
+ Instruction *RI = *I;
- // Replace the unwind instruction with a call to _Unwind_Resume (or the
- // appropriate target equivalent) followed by an UnreachableInst.
+ // Replace the resuming instruction with a call to _Unwind_Resume (or the
+ // appropriate target equivalent).
+
+ llvm::Value *ExnValue;
+ if (isa<UnwindInst>(RI))
+ ExnValue = CreateExceptionValueCall(RI->getParent());
+ else
+ ExnValue = cast<CallInst>(RI)->getArgOperand(0);
// Create the call...
- CallInst *CI = CallInst::Create(RewindFunction,
- CreateExceptionValueCall(TI->getParent()),
- "", TI);
+ CallInst *CI = CallInst::Create(RewindFunction, ExnValue, "", RI);
CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME));
- // ...followed by an UnreachableInst.
- new UnreachableInst(TI->getContext(), TI);
- // Nuke the unwind instruction.
- TI->eraseFromParent();
- ++NumUnwindsLowered;
+ // ...followed by an UnreachableInst, if it was an unwind.
+ // Calls to llvm.eh.resume are typically already followed by this.
+ if (isa<UnwindInst>(RI))
+ new UnreachableInst(RI->getContext(), RI);
+
+ // Nuke the resume instruction.
+ RI->eraseFromParent();
+
+ if (isa<UnwindInst>(RI))
+ ++NumUnwindsLowered;
+ else
+ ++NumResumesLowered;
Changed = true;
}
@@ -657,8 +674,8 @@ bool DwarfEHPrepare::runOnFunction(Function &Fn) {
// basic block where an invoke unwind edge ends).
Changed |= NormalizeLandingPads();
- // Turn unwind instructions into libcalls.
- Changed |= LowerUnwinds();
+ // Turn unwind instructions and eh.resume calls into libcalls.
+ Changed |= LowerUnwindsAndResumes();
// TODO: Move eh.selector calls to landing pads and combine them.