From 66c384ac2e65cf8bbae3fb5df3a4c1646913a473 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Sun, 8 Feb 2009 07:46:24 +0000 Subject: [PATCH] More cleanup stack work, PopCleanupBlock now returns a struct with the switch block and end block. llvm-svn: 64072 --- clang/lib/CodeGen/CodeGenFunction.cpp | 60 ++++++++++++++------------- clang/lib/CodeGen/CodeGenFunction.h | 36 ++++++++++------ 2 files changed, 56 insertions(+), 40 deletions(-) diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 2ab73648df4d..b62499d3adb3 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -531,10 +531,20 @@ void CodeGenFunction::EmitCleanupBlocks(size_t OldCleanupStackSize) EmitCleanupBlock(); } -void CodeGenFunction::FixupBranches(llvm::BasicBlock *CleanupBlock, - const BlockVector& Blocks, - BranchFixupsVector& BranchFixups) +CodeGenFunction::CleanupBlockInfo CodeGenFunction::PopCleanupBlock() { + CleanupEntry &CE = CleanupEntries.back(); + + llvm::BasicBlock *CleanupBlock = CE.CleanupBlock; + + std::vector Blocks; + std::swap(Blocks, CE.Blocks); + + std::vector BranchFixups; + std::swap(BranchFixups, CE.BranchFixups); + + CleanupEntries.pop_back(); + if (!CleanupEntries.empty()) { // Check if any branch fixups pointed to the scope we just popped. If so, // we can remove them. @@ -558,18 +568,26 @@ void CodeGenFunction::FixupBranches(llvm::BasicBlock *CleanupBlock, } } + llvm::BasicBlock *SwitchBlock = 0; + llvm::BasicBlock *EndBlock = 0; if (!BranchFixups.empty()) { - llvm::BasicBlock *CleanupEnd = createBasicBlock("cleanup.end"); + SwitchBlock = createBasicBlock("cleanup.switch"); + EndBlock = createBasicBlock("cleanup.end"); + llvm::BasicBlock *CurBB = Builder.GetInsertBlock(); + + Builder.SetInsertPoint(SwitchBlock); + llvm::Value *DestCodePtr = CreateTempAlloca(llvm::Type::Int32Ty, "cleanup.dst"); llvm::Value *DestCode = Builder.CreateLoad(DestCodePtr, "tmp"); // Create a switch instruction to determine where to jump next. - llvm::SwitchInst *SI = Builder.CreateSwitch(DestCode, CleanupEnd, + llvm::SwitchInst *SI = Builder.CreateSwitch(DestCode, EndBlock, BranchFixups.size()); - EmitBlock(CleanupEnd); - + + Builder.SetInsertPoint(CurBB); + for (size_t i = 0, e = BranchFixups.size(); i != e; ++i) { llvm::BranchInst *BI = BranchFixups[i]; llvm::BasicBlock *Dest = BI->getSuccessor(0); @@ -612,34 +630,20 @@ void CodeGenFunction::FixupBranches(llvm::BasicBlock *CleanupBlock, BlockScopes.erase(Blocks[i]); } -} - -llvm::BasicBlock * -CodeGenFunction::PopCleanupBlock(BlockVector& Blocks, - BranchFixupsVector& BranchFixups) -{ - CleanupEntry &CE = CleanupEntries.back(); - llvm::BasicBlock *CleanupBlock = CE.CleanupBlock; - - std::swap(Blocks, CE.Blocks); - std::swap(BranchFixups, CE.BranchFixups); - - CleanupEntries.pop_back(); - - return CleanupBlock; + return CleanupBlockInfo(CleanupBlock, SwitchBlock, EndBlock); } void CodeGenFunction::EmitCleanupBlock() { - BlockVector Blocks; - BranchFixupsVector BranchFixups; + CleanupBlockInfo Info = PopCleanupBlock(); - llvm::BasicBlock *CleanupBlock = PopCleanupBlock(Blocks, BranchFixups); + EmitBlock(Info.CleanupBlock); - EmitBlock(CleanupBlock); - - FixupBranches(CleanupBlock, Blocks, BranchFixups); + if (Info.SwitchBlock) + EmitBlock(Info.SwitchBlock); + if (Info.EndBlock) + EmitBlock(Info.EndBlock); } void CodeGenFunction::AddBranchFixup(llvm::BranchInst *BI) diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index fa23308176a7..836a36f95298 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -131,6 +131,28 @@ public: /// PushCleanupBlock - Push a new cleanup entry on the stack and set the /// passed in block as the cleanup block. void PushCleanupBlock(llvm::BasicBlock *CleanupBlock); + + /// CleanupBlockInfo - A struct representing a popped cleanup block + struct CleanupBlockInfo { + /// CleanupBlock - the cleanup block + llvm::BasicBlock *CleanupBlock; + + /// SwitchBlock - the block (if any) containing the switch instruction + /// used for jumping to the final destination. + llvm::BasicBlock *SwitchBlock; + + /// EndBlock - the default destination for the switch instruction. + llvm::BasicBlock *EndBlock; + + CleanupBlockInfo(llvm::BasicBlock *cb, llvm::BasicBlock *sb, + llvm::BasicBlock *eb) + : CleanupBlock(cb), SwitchBlock(sb), EndBlock(eb) {} + }; + + /// PopCleanupBlock - Will pop the cleanup entry on the stack, process all + /// branch fixups and return a block info struct with the switch block and + /// end block. + CleanupBlockInfo PopCleanupBlock(); /// CleanupScope - RAII object that will create a cleanup block and /// set the insert point to that block. When destructed, it sets the insert @@ -249,19 +271,16 @@ private: /// label. void EmitStackUpdate(const LabelStmt &S); - typedef std::vector BlockVector; - typedef std::vector BranchFixupsVector; - struct CleanupEntry { /// CleanupBlock - The block of code that does the actual cleanup. llvm::BasicBlock *CleanupBlock; /// Blocks - Basic blocks that were emitted in the current cleanup scope. - BlockVector Blocks; + std::vector Blocks; /// BranchFixups - Branch instructions to basic blocks that haven't been /// inserted into the current function yet. - BranchFixupsVector BranchFixups; + std::vector BranchFixups; explicit CleanupEntry(llvm::BasicBlock *cb) : CleanupBlock(cb) {} @@ -791,13 +810,6 @@ private: /// EmitCleanupBlock - emits a single cleanup block. void EmitCleanupBlock(); - llvm::BasicBlock *PopCleanupBlock(BlockVector& Blocks, - BranchFixupsVector& BranchFixups); - - void FixupBranches(llvm::BasicBlock *CleanupBlock, - const BlockVector& Blocks, - BranchFixupsVector& BranchFixups); - /// AddBranchFixup - adds a branch instruction to the list of fixups for the /// current cleanup scope. void AddBranchFixup(llvm::BranchInst *BI);