diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp | 74 |
1 files changed, 49 insertions, 25 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp index b2d0786..b00e2a2 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGCleanup.cpp @@ -84,7 +84,6 @@ RValue DominatingValue<RValue>::saved_type::restore(CodeGenFunction &CGF) { } llvm_unreachable("bad saved r-value kind"); - return RValue(); } /// Push an entry of the given size onto this protected-scope stack. @@ -251,8 +250,7 @@ void CodeGenFunction::initFullExprCleanup() { // Initialize it to false at a site that's guaranteed to be run // before each evaluation. - llvm::BasicBlock *block = OutermostConditional->getStartingBlock(); - new llvm::StoreInst(Builder.getFalse(), active, &block->back()); + setBeforeOutermostConditional(Builder.getFalse(), active); // Initialize it to true at the current location. Builder.CreateStore(Builder.getTrue(), active); @@ -504,9 +502,9 @@ static void destroyOptimisticNormalEntry(CodeGenFunction &CGF, // The only uses should be fixup switches. llvm::SwitchInst *si = cast<llvm::SwitchInst>(use.getUser()); - if (si->getNumCases() == 2 && si->getDefaultDest() == unreachableBB) { + if (si->getNumCases() == 1 && si->getDefaultDest() == unreachableBB) { // Replace the switch with a branch. - llvm::BranchInst::Create(si->getSuccessor(1), si); + llvm::BranchInst::Create(si->case_begin().getCaseSuccessor(), si); // The switch operand is a load from the cleanup-dest alloca. llvm::LoadInst *condition = cast<llvm::LoadInst>(si->getCondition()); @@ -1000,57 +998,75 @@ enum ForActivation_t { /// extra uses *after* the change-over point. static void SetupCleanupBlockActivation(CodeGenFunction &CGF, EHScopeStack::stable_iterator C, - ForActivation_t Kind) { + ForActivation_t kind, + llvm::Instruction *dominatingIP) { EHCleanupScope &Scope = cast<EHCleanupScope>(*CGF.EHStack.find(C)); - // We always need the flag if we're activating the cleanup, because - // we have to assume that the current location doesn't necessarily - // dominate all future uses of the cleanup. - bool NeedFlag = (Kind == ForActivation); + // We always need the flag if we're activating the cleanup in a + // conditional context, because we have to assume that the current + // location doesn't necessarily dominate the cleanup's code. + bool isActivatedInConditional = + (kind == ForActivation && CGF.isInConditionalBranch()); + + bool needFlag = false; // Calculate whether the cleanup was used: // - as a normal cleanup - if (Scope.isNormalCleanup() && IsUsedAsNormalCleanup(CGF.EHStack, C)) { + if (Scope.isNormalCleanup() && + (isActivatedInConditional || IsUsedAsNormalCleanup(CGF.EHStack, C))) { Scope.setTestFlagInNormalCleanup(); - NeedFlag = true; + needFlag = true; } // - as an EH cleanup - if (Scope.isEHCleanup() && IsUsedAsEHCleanup(CGF.EHStack, C)) { + if (Scope.isEHCleanup() && + (isActivatedInConditional || IsUsedAsEHCleanup(CGF.EHStack, C))) { Scope.setTestFlagInEHCleanup(); - NeedFlag = true; + needFlag = true; } // If it hasn't yet been used as either, we're done. - if (!NeedFlag) return; + if (!needFlag) return; - llvm::AllocaInst *Var = Scope.getActiveFlag(); - if (!Var) { - Var = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(), "cleanup.isactive"); - Scope.setActiveFlag(Var); + llvm::AllocaInst *var = Scope.getActiveFlag(); + if (!var) { + var = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(), "cleanup.isactive"); + Scope.setActiveFlag(var); + + assert(dominatingIP && "no existing variable and no dominating IP!"); // Initialize to true or false depending on whether it was // active up to this point. - CGF.InitTempAlloca(Var, CGF.Builder.getInt1(Kind == ForDeactivation)); + llvm::Value *value = CGF.Builder.getInt1(kind == ForDeactivation); + + // If we're in a conditional block, ignore the dominating IP and + // use the outermost conditional branch. + if (CGF.isInConditionalBranch()) { + CGF.setBeforeOutermostConditional(value, var); + } else { + new llvm::StoreInst(value, var, dominatingIP); + } } - CGF.Builder.CreateStore(CGF.Builder.getInt1(Kind == ForActivation), Var); + CGF.Builder.CreateStore(CGF.Builder.getInt1(kind == ForActivation), var); } /// Activate a cleanup that was created in an inactivated state. -void CodeGenFunction::ActivateCleanupBlock(EHScopeStack::stable_iterator C) { +void CodeGenFunction::ActivateCleanupBlock(EHScopeStack::stable_iterator C, + llvm::Instruction *dominatingIP) { assert(C != EHStack.stable_end() && "activating bottom of stack?"); EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(C)); assert(!Scope.isActive() && "double activation"); - SetupCleanupBlockActivation(*this, C, ForActivation); + SetupCleanupBlockActivation(*this, C, ForActivation, dominatingIP); Scope.setActive(true); } /// Deactive a cleanup that was created in an active state. -void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C) { +void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C, + llvm::Instruction *dominatingIP) { assert(C != EHStack.stable_end() && "deactivating bottom of stack?"); EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(C)); assert(Scope.isActive() && "double deactivation"); @@ -1066,7 +1082,7 @@ void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C) { } // Otherwise, follow the general case. - SetupCleanupBlockActivation(*this, C, ForDeactivation); + SetupCleanupBlockActivation(*this, C, ForDeactivation, dominatingIP); Scope.setActive(false); } @@ -1077,3 +1093,11 @@ llvm::Value *CodeGenFunction::getNormalCleanupDestSlot() { CreateTempAlloca(Builder.getInt32Ty(), "cleanup.dest.slot"); return NormalCleanupDest; } + +/// Emits all the code to cause the given temporary to be cleaned up. +void CodeGenFunction::EmitCXXTemporary(const CXXTemporary *Temporary, + QualType TempType, + llvm::Value *Ptr) { + pushDestroy(NormalAndEHCleanup, Ptr, TempType, destroyCXXObject, + /*useEHCleanup*/ true); +} |