From: Anders Carlsson Date: Sun, 8 Feb 2009 07:46:24 +0000 (+0000) Subject: More cleanup stack work, PopCleanupBlock now returns a struct with the switch block... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bb66f9f2e454135b86462d121629275b6ac38e96;p=clang More cleanup stack work, PopCleanupBlock now returns a struct with the switch block and end block. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64072 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 2ab73648df..b62499d3ad 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/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/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index fa23308176..836a36f952 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/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);