More cleanup stack work, PopCleanupBlock now returns a struct with the switch block and end block.

llvm-svn: 64072
This commit is contained in:
Anders Carlsson 2009-02-08 07:46:24 +00:00
parent beb1ce6504
commit 66c384ac2e
2 changed files with 56 additions and 40 deletions

View File

@ -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<llvm::BasicBlock *> Blocks;
std::swap(Blocks, CE.Blocks);
std::vector<llvm::BranchInst *> 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)

View File

@ -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<llvm::BasicBlock *> BlockVector;
typedef std::vector<llvm::BranchInst *> 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<llvm::BasicBlock *> Blocks;
/// BranchFixups - Branch instructions to basic blocks that haven't been
/// inserted into the current function yet.
BranchFixupsVector BranchFixups;
std::vector<llvm::BranchInst *> 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);