More cleanup stack work, PopCleanupBlock now returns a struct with the switch block and end block.
llvm-svn: 64072
This commit is contained in:
parent
beb1ce6504
commit
66c384ac2e
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue