X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FDwarfEHPrepare.cpp;h=c7c1752665647683829418825e02b7898cd94249;hb=e2ff00e117ba9b758b298e671f65c0b002f8a52d;hp=f2b2977275197b0cca3b2364e0a7162d74186f02;hpb=b618ea5ff97182381107ab6bf52b0c2d8f783d7d;p=oota-llvm.git diff --git a/lib/CodeGen/DwarfEHPrepare.cpp b/lib/CodeGen/DwarfEHPrepare.cpp index f2b29772751..c7c17526656 100644 --- a/lib/CodeGen/DwarfEHPrepare.cpp +++ b/lib/CodeGen/DwarfEHPrepare.cpp @@ -13,15 +13,15 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "dwarfehprepare" -#include "llvm/Function.h" -#include "llvm/Instructions.h" -#include "llvm/IntrinsicInst.h" -#include "llvm/Module.h" -#include "llvm/Pass.h" +#include "llvm/CodeGen/Passes.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/Dominators.h" -#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/Pass.h" #include "llvm/Support/CallSite.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" @@ -33,18 +33,17 @@ STATISTIC(NumResumesLowered, "Number of resume calls lowered"); namespace { class DwarfEHPrepare : public FunctionPass { const TargetMachine *TM; - const TargetLowering *TLI; // RewindFunction - _Unwind_Resume or the target equivalent. Constant *RewindFunction; bool InsertUnwindResumeCalls(Function &Fn); + Value *GetExceptionObject(ResumeInst *RI); public: static char ID; // Pass identification, replacement for typeid. - DwarfEHPrepare(const TargetMachine *tm) : - FunctionPass(ID), TM(tm), TLI(TM->getTargetLowering()), - RewindFunction(0) { + DwarfEHPrepare(const TargetMachine *TM) : + FunctionPass(ID), TM(TM), RewindFunction(0) { initializeDominatorTreePass(*PassRegistry::getPassRegistry()); } @@ -60,27 +59,65 @@ namespace { char DwarfEHPrepare::ID = 0; -FunctionPass *llvm::createDwarfEHPass(const TargetMachine *tm) { - return new DwarfEHPrepare(tm); +FunctionPass *llvm::createDwarfEHPass(const TargetMachine *TM) { + return new DwarfEHPrepare(TM); +} + +/// GetExceptionObject - Return the exception object from the value passed into +/// the 'resume' instruction (typically an aggregate). Clean up any dead +/// instructions, including the 'resume' instruction. +Value *DwarfEHPrepare::GetExceptionObject(ResumeInst *RI) { + Value *V = RI->getOperand(0); + Value *ExnObj = 0; + InsertValueInst *SelIVI = dyn_cast(V); + LoadInst *SelLoad = 0; + InsertValueInst *ExcIVI = 0; + bool EraseIVIs = false; + + if (SelIVI) { + if (SelIVI->getNumIndices() == 1 && *SelIVI->idx_begin() == 1) { + ExcIVI = dyn_cast(SelIVI->getOperand(0)); + if (ExcIVI && isa(ExcIVI->getOperand(0)) && + ExcIVI->getNumIndices() == 1 && *ExcIVI->idx_begin() == 0) { + ExnObj = ExcIVI->getOperand(1); + SelLoad = dyn_cast(SelIVI->getOperand(1)); + EraseIVIs = true; + } + } + } + + if (!ExnObj) + ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", RI); + + RI->eraseFromParent(); + + if (EraseIVIs) { + if (SelIVI->getNumUses() == 0) + SelIVI->eraseFromParent(); + if (ExcIVI->getNumUses() == 0) + ExcIVI->eraseFromParent(); + if (SelLoad && SelLoad->getNumUses() == 0) + SelLoad->eraseFromParent(); + } + + return ExnObj; } /// InsertUnwindResumeCalls - Convert the ResumeInsts that are still present /// into calls to the appropriate _Unwind_Resume function. bool DwarfEHPrepare::InsertUnwindResumeCalls(Function &Fn) { - bool UsesNewEH = false; SmallVector Resumes; for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) { TerminatorInst *TI = I->getTerminator(); if (ResumeInst *RI = dyn_cast(TI)) Resumes.push_back(RI); - else if (InvokeInst *II = dyn_cast(TI)) - UsesNewEH = II->getUnwindDest()->isLandingPad(); } if (Resumes.empty()) - return UsesNewEH; + return false; // Find the rewind function if we didn't already. + const TargetLowering *TLI = TM->getTargetLowering(); if (!RewindFunction) { LLVMContext &Ctx = Resumes[0]->getContext(); FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx), @@ -91,8 +128,26 @@ bool DwarfEHPrepare::InsertUnwindResumeCalls(Function &Fn) { // Create the basic block where the _Unwind_Resume call will live. LLVMContext &Ctx = Fn.getContext(); + unsigned ResumesSize = Resumes.size(); + + if (ResumesSize == 1) { + // Instead of creating a new BB and PHI node, just append the call to + // _Unwind_Resume to the end of the single resume block. + ResumeInst *RI = Resumes.front(); + BasicBlock *UnwindBB = RI->getParent(); + Value *ExnObj = GetExceptionObject(RI); + + // Call the _Unwind_Resume function. + CallInst *CI = CallInst::Create(RewindFunction, ExnObj, "", UnwindBB); + CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME)); + + // We never expect _Unwind_Resume to return. + new UnreachableInst(Ctx, UnwindBB); + return true; + } + BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", &Fn); - PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), Resumes.size(), + PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), ResumesSize, "exn.obj", UnwindBB); // Extract the exception object from the ResumeInst and add it to the PHI node @@ -100,40 +155,11 @@ bool DwarfEHPrepare::InsertUnwindResumeCalls(Function &Fn) { for (SmallVectorImpl::iterator I = Resumes.begin(), E = Resumes.end(); I != E; ++I) { ResumeInst *RI = *I; - BranchInst::Create(UnwindBB, RI->getParent()); - - Value *V = RI->getOperand(0); - Instruction *ExnObj = 0; - InsertValueInst *SelIVI = dyn_cast(V); - LoadInst *SelLoad = 0; - InsertValueInst *ExcIVI = 0; - bool EraseIVIs = false; - if (SelIVI) { - if (SelIVI->getNumIndices() == 1 && *SelIVI->idx_begin() == 1) { - ExcIVI = dyn_cast(SelIVI->getOperand(0)); - if (ExcIVI && isa(ExcIVI->getOperand(0)) && - ExcIVI->getNumIndices() == 1 && *ExcIVI->idx_begin() == 0) { - ExnObj = cast(ExcIVI->getOperand(1)); - SelLoad = dyn_cast(SelIVI->getOperand(1)); - EraseIVIs = true; - } - } - } - - if (!ExnObj) - ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", RI); + BasicBlock *Parent = RI->getParent(); + BranchInst::Create(UnwindBB, Parent); - PN->addIncoming(ExnObj, RI->getParent()); - RI->eraseFromParent(); - - if (EraseIVIs) { - if (SelIVI->getNumUses() == 0) - SelIVI->eraseFromParent(); - if (ExcIVI->getNumUses() == 0) - ExcIVI->eraseFromParent(); - if (SelLoad && SelLoad->getNumUses() == 0) - SelLoad->eraseFromParent(); - } + Value *ExnObj = GetExceptionObject(RI); + PN->addIncoming(ExnObj, Parent); ++NumResumesLowered; }