This patch extends CleanupScope to support destruction

of array objects on block exit. Patch is by Anders Calrsson.

llvm-svn: 86032
This commit is contained in:
Fariborz Jahanian 2009-11-04 17:57:40 +00:00
parent 2de8f4149e
commit 09cc10f9f8
4 changed files with 41 additions and 25 deletions

View File

@ -515,20 +515,24 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
const CXXDestructorDecl *D = ClassDecl->getDestructor(getContext()); const CXXDestructorDecl *D = ClassDecl->getDestructor(getContext());
assert(D && "EmitLocalBlockVarDecl - destructor is nul"); assert(D && "EmitLocalBlockVarDecl - destructor is nul");
CleanupScope scope(*this);
if (const ConstantArrayType *Array = if (const ConstantArrayType *Array =
getContext().getAsConstantArrayType(Ty)) { getContext().getAsConstantArrayType(Ty)) {
CleanupScope Scope(*this);
QualType BaseElementTy = getContext().getBaseElementType(Array); QualType BaseElementTy = getContext().getBaseElementType(Array);
const llvm::Type *BasePtr = ConvertType(BaseElementTy); const llvm::Type *BasePtr = ConvertType(BaseElementTy);
BasePtr = llvm::PointerType::getUnqual(BasePtr); BasePtr = llvm::PointerType::getUnqual(BasePtr);
llvm::Value *BaseAddrPtr = llvm::Value *BaseAddrPtr =
Builder.CreateBitCast(DeclPtr, BasePtr); Builder.CreateBitCast(DeclPtr, BasePtr);
EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr); EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr);
}
else // Make sure to jump to the exit block.
EmitBranch(Scope.getCleanupExitBlock());
} else {
CleanupScope Scope(*this);
EmitCXXDestructorCall(D, Dtor_Complete, DeclPtr); EmitCXXDestructorCall(D, Dtor_Complete, DeclPtr);
} }
} }
}
// Handle the cleanup attribute // Handle the cleanup attribute
if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) { if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) {

View File

@ -665,8 +665,9 @@ llvm::Value* CodeGenFunction::EmitVAListRef(const Expr* E) {
return EmitLValue(E).getAddress(); return EmitLValue(E).getAddress();
} }
void CodeGenFunction::PushCleanupBlock(llvm::BasicBlock *CleanupBlock) { void CodeGenFunction::PushCleanupBlock(llvm::BasicBlock *CleanupEntryBlock,
CleanupEntries.push_back(CleanupEntry(CleanupBlock)); llvm::BasicBlock *CleanupExitBlock) {
CleanupEntries.push_back(CleanupEntry(CleanupEntryBlock, CleanupExitBlock));
} }
void CodeGenFunction::EmitCleanupBlocks(size_t OldCleanupStackSize) { void CodeGenFunction::EmitCleanupBlocks(size_t OldCleanupStackSize) {
@ -680,7 +681,7 @@ void CodeGenFunction::EmitCleanupBlocks(size_t OldCleanupStackSize) {
CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() { CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() {
CleanupEntry &CE = CleanupEntries.back(); CleanupEntry &CE = CleanupEntries.back();
llvm::BasicBlock *CleanupBlock = CE.CleanupBlock; llvm::BasicBlock *CleanupEntryBlock = CE.CleanupEntryBlock;
std::vector<llvm::BasicBlock *> Blocks; std::vector<llvm::BasicBlock *> Blocks;
std::swap(Blocks, CE.Blocks); std::swap(Blocks, CE.Blocks);
@ -711,9 +712,10 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() {
} }
} }
llvm::BasicBlock *SwitchBlock = 0; llvm::BasicBlock *SwitchBlock = CE.CleanupExitBlock;
llvm::BasicBlock *EndBlock = 0; llvm::BasicBlock *EndBlock = 0;
if (!BranchFixups.empty()) { if (!BranchFixups.empty()) {
if (!SwitchBlock)
SwitchBlock = createBasicBlock("cleanup.switch"); SwitchBlock = createBasicBlock("cleanup.switch");
EndBlock = createBasicBlock("cleanup.end"); EndBlock = createBasicBlock("cleanup.end");
@ -745,7 +747,7 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() {
llvm::BasicBlock *Dest = BI->getSuccessor(0); llvm::BasicBlock *Dest = BI->getSuccessor(0);
// Fixup the branch instruction to point to the cleanup block. // Fixup the branch instruction to point to the cleanup block.
BI->setSuccessor(0, CleanupBlock); BI->setSuccessor(0, CleanupEntryBlock);
if (CleanupEntries.empty()) { if (CleanupEntries.empty()) {
llvm::ConstantInt *ID; llvm::ConstantInt *ID;
@ -802,7 +804,7 @@ CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() {
BlockScopes.erase(Blocks[i]); BlockScopes.erase(Blocks[i]);
} }
return CleanupBlockInfo(CleanupBlock, SwitchBlock, EndBlock); return CleanupBlockInfo(CleanupEntryBlock, SwitchBlock, EndBlock);
} }
void CodeGenFunction::EmitCleanupBlock() { void CodeGenFunction::EmitCleanupBlock() {

View File

@ -108,11 +108,12 @@ public:
/// PushCleanupBlock - Push a new cleanup entry on the stack and set the /// PushCleanupBlock - Push a new cleanup entry on the stack and set the
/// passed in block as the cleanup block. /// passed in block as the cleanup block.
void PushCleanupBlock(llvm::BasicBlock *CleanupBlock); void PushCleanupBlock(llvm::BasicBlock *CleanupEntryBlock,
llvm::BasicBlock *CleanupExitBlock = 0);
/// CleanupBlockInfo - A struct representing a popped cleanup block. /// CleanupBlockInfo - A struct representing a popped cleanup block.
struct CleanupBlockInfo { struct CleanupBlockInfo {
/// CleanupBlock - the cleanup block /// CleanupEntryBlock - the cleanup entry block
llvm::BasicBlock *CleanupBlock; llvm::BasicBlock *CleanupBlock;
/// SwitchBlock - the block (if any) containing the switch instruction used /// SwitchBlock - the block (if any) containing the switch instruction used
@ -138,17 +139,24 @@ public:
class CleanupScope { class CleanupScope {
CodeGenFunction& CGF; CodeGenFunction& CGF;
llvm::BasicBlock *CurBB; llvm::BasicBlock *CurBB;
llvm::BasicBlock *CleanupBB; llvm::BasicBlock *CleanupEntryBB;
llvm::BasicBlock *CleanupExitBB;
public: public:
CleanupScope(CodeGenFunction &cgf) CleanupScope(CodeGenFunction &cgf)
: CGF(cgf), CurBB(CGF.Builder.GetInsertBlock()) { : CGF(cgf), CurBB(CGF.Builder.GetInsertBlock()),
CleanupBB = CGF.createBasicBlock("cleanup"); CleanupEntryBB(CGF.createBasicBlock("cleanup")), CleanupExitBB(0) {
CGF.Builder.SetInsertPoint(CleanupBB); CGF.Builder.SetInsertPoint(CleanupEntryBB);
}
llvm::BasicBlock *getCleanupExitBlock() {
if (!CleanupExitBB)
CleanupExitBB = CGF.createBasicBlock("cleanup.exit");
return CleanupExitBB;
} }
~CleanupScope() { ~CleanupScope() {
CGF.PushCleanupBlock(CleanupBB); CGF.PushCleanupBlock(CleanupEntryBB, CleanupExitBB);
// FIXME: This is silly, move this into the builder. // FIXME: This is silly, move this into the builder.
if (CurBB) if (CurBB)
CGF.Builder.SetInsertPoint(CurBB); CGF.Builder.SetInsertPoint(CurBB);
@ -250,8 +258,11 @@ private:
bool DidCallStackSave; bool DidCallStackSave;
struct CleanupEntry { struct CleanupEntry {
/// CleanupBlock - The block of code that does the actual cleanup. /// CleanupEntryBlock - The block of code that does the actual cleanup.
llvm::BasicBlock *CleanupBlock; llvm::BasicBlock *CleanupEntryBlock;
/// CleanupExitBlock - The cleanup exit block.
llvm::BasicBlock *CleanupExitBlock;
/// Blocks - Basic blocks that were emitted in the current cleanup scope. /// Blocks - Basic blocks that were emitted in the current cleanup scope.
std::vector<llvm::BasicBlock *> Blocks; std::vector<llvm::BasicBlock *> Blocks;
@ -260,8 +271,10 @@ private:
/// inserted into the current function yet. /// inserted into the current function yet.
std::vector<llvm::BranchInst *> BranchFixups; std::vector<llvm::BranchInst *> BranchFixups;
explicit CleanupEntry(llvm::BasicBlock *cb) explicit CleanupEntry(llvm::BasicBlock *CleanupEntryBlock,
: CleanupBlock(cb) {} llvm::BasicBlock *CleanupExitBlock)
: CleanupEntryBlock(CleanupEntryBlock),
CleanupExitBlock(CleanupExitBlock) {}
}; };
/// CleanupEntries - Stack of cleanup entries. /// CleanupEntries - Stack of cleanup entries.

View File

@ -17,12 +17,9 @@ public:
int i; int i;
float f; float f;
/**
NYI
~xpto() { ~xpto() {
printf("xpto::~xpto()\n"); printf("xpto::~xpto()\n");
} }
*/
}; };
int main() { int main() {