X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FDwarfEHPrepare.cpp;h=39fc85e7649eb81f9dbd6d73b5d6aac858a93909;hb=3b131d7cc4dc4bbb329c136705b37dc255995fbd;hp=5bfb32870c9801ebf816544c9779cca9039675bc;hpb=debcb01b0f0a15f568ca69e8f288fade4bfc7297;p=oota-llvm.git diff --git a/lib/CodeGen/DwarfEHPrepare.cpp b/lib/CodeGen/DwarfEHPrepare.cpp index 5bfb32870c9..39fc85e7649 100644 --- a/lib/CodeGen/DwarfEHPrepare.cpp +++ b/lib/CodeGen/DwarfEHPrepare.cpp @@ -21,7 +21,7 @@ #include "llvm/IntrinsicInst.h" #include "llvm/Module.h" #include "llvm/Pass.h" -#include "llvm/Support/Compiler.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/PromoteMemToReg.h" @@ -33,7 +33,7 @@ STATISTIC(NumExceptionValuesMoved, "Number of eh.exception calls moved"); STATISTIC(NumStackTempsIntroduced, "Number of stack temporaries introduced"); namespace { - class VISIBILITY_HIDDEN DwarfEHPrepare : public FunctionPass { + class DwarfEHPrepare : public FunctionPass { const TargetLowering *TLI; bool CompileFast; @@ -107,12 +107,17 @@ FunctionPass *llvm::createDwarfEHPass(const TargetLowering *tli, bool fast) { /// NormalizeLandingPads - Normalize and discover landing pads, noting them /// in the LandingPads set. A landing pad is normal if the only CFG edges -/// that end at it are unwind edges from invoke instructions. +/// that end at it are unwind edges from invoke instructions. If we inlined +/// through an invoke we could have a normal branch from the previous +/// unwind block through to the landing pad for the original invoke. /// Abnormal landing pads are fixed up by redirecting all unwind edges to /// a new basic block which falls through to the original. bool DwarfEHPrepare::NormalizeLandingPads() { bool Changed = false; + const MCAsmInfo *MAI = TLI->getTargetMachine().getMCAsmInfo(); + bool usingSjLjEH = MAI->getExceptionHandlingType() == ExceptionHandling::SjLj; + for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) { TerminatorInst *TI = I->getTerminator(); if (!isa(TI)) @@ -124,14 +129,24 @@ bool DwarfEHPrepare::NormalizeLandingPads() { // Check that only invoke unwind edges end at the landing pad. bool OnlyUnwoundTo = true; + bool SwitchOK = usingSjLjEH; for (pred_iterator PI = pred_begin(LPad), PE = pred_end(LPad); PI != PE; ++PI) { TerminatorInst *PT = (*PI)->getTerminator(); + // The SjLj dispatch block uses a switch instruction. This is effectively + // an unwind edge, so we can disregard it here. There will only ever + // be one dispatch, however, so if there are multiple switches, one + // of them truly is a normal edge, not an unwind edge. + if (SwitchOK && isa(PT)) { + SwitchOK = false; + continue; + } if (!isa(PT) || LPad == PT->getSuccessor(0)) { OnlyUnwoundTo = false; break; } } + if (OnlyUnwoundTo) { // Only unwind edges lead to the landing pad. Remember the landing pad. LandingPads.insert(LPad); @@ -142,7 +157,8 @@ bool DwarfEHPrepare::NormalizeLandingPads() { // edges to a new basic block which falls through into this one. // Create the new basic block. - BasicBlock *NewBB = BasicBlock::Create(LPad->getName() + "_unwind_edge"); + BasicBlock *NewBB = BasicBlock::Create(F->getContext(), + LPad->getName() + "_unwind_edge"); // Insert it into the function right before the original landing pad. LPad->getParent()->getBasicBlockList().insert(LPad, NewBB); @@ -218,28 +234,43 @@ bool DwarfEHPrepare::NormalizeLandingPads() { /// at runtime if there is no such exception: using unwind to throw a new /// exception is currently not supported. bool DwarfEHPrepare::LowerUnwinds() { - bool Changed = false; + SmallVector UnwindInsts; for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) { TerminatorInst *TI = I->getTerminator(); - if (!isa(TI)) - continue; + if (isa(TI)) + UnwindInsts.push_back(TI); + } + + if (UnwindInsts.empty()) return false; + + // Find the rewind function if we didn't already. + if (!RewindFunction) { + LLVMContext &Ctx = UnwindInsts[0]->getContext(); + std::vector + Params(1, Type::getInt8PtrTy(Ctx)); + FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx), + Params, false); + const char *RewindName = TLI->getLibcallName(RTLIB::UNWIND_RESUME); + RewindFunction = F->getParent()->getOrInsertFunction(RewindName, FTy); + } + + bool Changed = false; + + for (SmallVectorImpl::iterator + I = UnwindInsts.begin(), E = UnwindInsts.end(); I != E; ++I) { + TerminatorInst *TI = *I; // Replace the unwind instruction with a call to _Unwind_Resume (or the // appropriate target equivalent) followed by an UnreachableInst. - // Find the rewind function if we didn't already. - if (!RewindFunction) { - std::vector Params(1, PointerType::getUnqual(Type::Int8Ty)); - FunctionType *FTy = FunctionType::get(Type::VoidTy, Params, false); - const char *RewindName = TLI->getLibcallName(RTLIB::UNWIND_RESUME); - RewindFunction = F->getParent()->getOrInsertFunction(RewindName, FTy); - } - // Create the call... - CallInst::Create(RewindFunction, CreateReadOfExceptionValue(I), "", TI); + CallInst *CI = CallInst::Create(RewindFunction, + CreateReadOfExceptionValue(TI->getParent()), + "", TI); + CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME)); // ...followed by an UnreachableInst. - new UnreachableInst(TI); + new UnreachableInst(TI->getContext(), TI); // Nuke the unwind instruction. TI->eraseFromParent(); @@ -314,7 +345,7 @@ bool DwarfEHPrepare::PromoteStackTemporaries() { if (ExceptionValueVar && DT && DF && isAllocaPromotable(ExceptionValueVar)) { // Turn the exception temporary into registers and phi nodes if possible. std::vector Allocas(1, ExceptionValueVar); - PromoteMemToReg(Allocas, *DT, *DF, ExceptionValueVar->getContext()); + PromoteMemToReg(Allocas, *DT, *DF); return true; } return false; @@ -354,8 +385,8 @@ Instruction *DwarfEHPrepare::CreateValueLoad(BasicBlock *BB) { // Create the temporary if we didn't already. if (!ExceptionValueVar) { - ExceptionValueVar = new AllocaInst(PointerType::getUnqual(Type::Int8Ty), - "eh.value", F->begin()->begin()); + ExceptionValueVar = new AllocaInst(PointerType::getUnqual( + Type::getInt8Ty(BB->getContext())), "eh.value", F->begin()->begin()); ++NumStackTempsIntroduced; }