diff options
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 60 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 15 | 
2 files changed, 50 insertions, 25 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index e9bcfb51dc2..2ab73648df4 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -531,34 +531,22 @@ void CodeGenFunction::EmitCleanupBlocks(size_t OldCleanupStackSize)      EmitCleanupBlock();  } -void CodeGenFunction::EmitCleanupBlock() +void CodeGenFunction::FixupBranches(llvm::BasicBlock *CleanupBlock, +                                    const BlockVector& Blocks, +                                    BranchFixupsVector& BranchFixups)  { -  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(); -   -  EmitBlock(CleanupBlock); -    if (!CleanupEntries.empty()) {      // Check if any branch fixups pointed to the scope we just popped. If so,      // we can remove them.      for (size_t i = 0, e = BranchFixups.size(); i != e; ++i) {        llvm::BasicBlock *Dest = BranchFixups[i]->getSuccessor(0);        BlockScopeMap::iterator I = BlockScopes.find(Dest); -     +              if (I == BlockScopes.end())          continue;        assert(I->second <= CleanupEntries.size() && "Invalid branch fixup!"); - +              if (I->second == CleanupEntries.size()) {          // We don't need to do this branch fixup.          BranchFixups[i] = BranchFixups.back(); @@ -569,7 +557,7 @@ void CodeGenFunction::EmitCleanupBlock()        }      }    } - +      if (!BranchFixups.empty()) {      llvm::BasicBlock *CleanupEnd = createBasicBlock("cleanup.end"); @@ -588,12 +576,12 @@ void CodeGenFunction::EmitCleanupBlock()        // Store the jump destination before the branch instruction.        llvm::ConstantInt *DI =  -        llvm::ConstantInt::get(llvm::Type::Int32Ty, i + 1); +      llvm::ConstantInt::get(llvm::Type::Int32Ty, i + 1);        new llvm::StoreInst(DI, DestCodePtr, BI);        // Fixup the branch instruction to point to the cleanup block.        BI->setSuccessor(0, CleanupBlock); - +              if (CleanupEntries.empty()) {          SI->addCase(DI, Dest);        } else { @@ -603,7 +591,7 @@ void CodeGenFunction::EmitCleanupBlock()          // Create the pad block.          llvm::BasicBlock *CleanupPad = createBasicBlock("cleanup.pad", CurFn); - +                  // Add it as the destination.          SI->addCase(DI, CleanupPad); @@ -616,7 +604,7 @@ void CodeGenFunction::EmitCleanupBlock()        }      }    } - +      // Remove all blocks from the block scope map.    for (size_t i = 0, e = Blocks.size(); i != e; ++i) {      assert(BlockScopes.count(Blocks[i]) && @@ -626,6 +614,34 @@ void CodeGenFunction::EmitCleanupBlock()    }  } +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; +} + +void CodeGenFunction::EmitCleanupBlock() +{ +  BlockVector Blocks; +  BranchFixupsVector BranchFixups; +   +  llvm::BasicBlock *CleanupBlock = PopCleanupBlock(Blocks, BranchFixups); +   +  EmitBlock(CleanupBlock); + +  FixupBranches(CleanupBlock, Blocks, BranchFixups); +} +  void CodeGenFunction::AddBranchFixup(llvm::BranchInst *BI)  {    assert(!CleanupEntries.empty() &&  diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 9eae28ca2af..fa23308176a 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -249,16 +249,19 @@ 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. -    std::vector<llvm::BasicBlock *> Blocks; +    BlockVector Blocks;      /// BranchFixups - Branch instructions to basic blocks that haven't been      /// inserted into the current function yet. -    std::vector<llvm::BranchInst*> BranchFixups; +    BranchFixupsVector BranchFixups;      explicit CleanupEntry(llvm::BasicBlock *cb)        : CleanupBlock(cb) {} @@ -267,7 +270,6 @@ private:        assert(Blocks.empty() && "Did not empty blocks!");        assert(BranchFixups.empty() && "Did not empty branch fixups!");      } -        };    /// CleanupEntries - Stack of cleanup entries. @@ -789,6 +791,13 @@ 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);  | 

