zcov: / lib/CodeGen/CGTemporaries.cpp


Files: 1 Branches Taken: 61.9% 26 / 42
Generated: 2010-02-10 01:31 Branches Executed: 85.7% 36 / 42
Line Coverage: 77.3% 51 / 66


Programs: 1 Runs 2897


       1                 : //===--- CGTemporaries.cpp - Emit LLVM Code for C++ temporaries -----------===//
       2                 : //
       3                 : //                     The LLVM Compiler Infrastructure
       4                 : //
       5                 : // This file is distributed under the University of Illinois Open Source
       6                 : // License. See LICENSE.TXT for details.
       7                 : //
       8                 : //===----------------------------------------------------------------------===//
       9                 : //
      10                 : // This contains code dealing with C++ code generation of temporaries
      11                 : //
      12                 : //===----------------------------------------------------------------------===//
      13                 : 
      14                 : #include "CodeGenFunction.h"
      15                 : using namespace clang;
      16                 : using namespace CodeGen;
      17                 : 
      18                 : void CodeGenFunction::PushCXXTemporary(const CXXTemporary *Temporary,
      19               62:                                        llvm::Value *Ptr) {
      20                 :   assert((LiveTemporaries.empty() ||
      21                 :           LiveTemporaries.back().ThisPtr != Ptr ||
      22                 :           ConditionalBranchLevel) &&
                       18: branch 1 taken
                       44: branch 2 taken
                        0: branch 4 not taken
                       18: branch 5 taken
                       18: branch 6 taken
                       18: branch 7 taken
      23               62:          "Pushed the same temporary twice; AST is likely wrong");
      24               62:   llvm::BasicBlock *DtorBlock = createBasicBlock("temp.dtor");
      25                 : 
      26               62:   llvm::Value *CondPtr = 0;
      27                 : 
      28                 :   // Check if temporaries need to be conditional. If so, we'll create a
      29                 :   // condition boolean, initialize it to 0 and
                        9: branch 0 taken
                       53: branch 1 taken
      30               62:   if (ConditionalBranchLevel != 0) {
      31                9:     CondPtr = CreateTempAlloca(llvm::Type::getInt1Ty(VMContext), "cond");
      32                 : 
      33                 :     // Initialize it to false. This initialization takes place right after
      34                 :     // the alloca insert point.
      35                 :     llvm::StoreInst *SI =
      36                9:       new llvm::StoreInst(llvm::ConstantInt::getFalse(VMContext), CondPtr);
      37                9:     llvm::BasicBlock *Block = AllocaInsertPt->getParent();
      38                9:     Block->getInstList().insertAfter((llvm::Instruction *)AllocaInsertPt, SI);
      39                 : 
      40                 :     // Now set it to true.
      41                9:     Builder.CreateStore(llvm::ConstantInt::getTrue(VMContext), CondPtr);
      42                 :   }
      43                 : 
      44                 :   LiveTemporaries.push_back(CXXLiveTemporaryInfo(Temporary, Ptr, DtorBlock,
      45               62:                                                  CondPtr));
      46                 : 
      47               62:   PushCleanupBlock(DtorBlock);
      48                 : 
                        1: branch 0 taken
                       61: branch 1 taken
      49               62:   if (Exceptions) {
      50                1:     const CXXLiveTemporaryInfo& Info = LiveTemporaries.back();
      51                1:     llvm::BasicBlock *CondEnd = 0;
      52                 :     
      53                1:     EHCleanupBlock Cleanup(*this);
      54                 : 
      55                 :     // If this is a conditional temporary, we need to check the condition
      56                 :     // boolean and only call the destructor if it's true.
                        0: branch 0 not taken
                        1: branch 1 taken
      57                1:     if (Info.CondPtr) {
      58                0:       llvm::BasicBlock *CondBlock = createBasicBlock("cond.dtor.call");
      59                0:       CondEnd = createBasicBlock("cond.dtor.end");
      60                 : 
      61                0:       llvm::Value *Cond = Builder.CreateLoad(Info.CondPtr);
      62                0:       Builder.CreateCondBr(Cond, CondBlock, CondEnd);
      63                0:       EmitBlock(CondBlock);
      64                 :     }
      65                 : 
      66                 :     EmitCXXDestructorCall(Info.Temporary->getDestructor(),
      67                1:                           Dtor_Complete, Info.ThisPtr);
      68                 : 
                        0: branch 0 not taken
                        1: branch 1 taken
      69                1:     if (CondEnd) {
      70                 :       // Reset the condition. to false.
      71                0:       Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), Info.CondPtr);
      72                0:       EmitBlock(CondEnd);
      73                1:     }
      74                 :   }
      75               62: }
      76                 : 
      77               62: void CodeGenFunction::PopCXXTemporary() {
      78               62:   const CXXLiveTemporaryInfo& Info = LiveTemporaries.back();
      79                 : 
      80               62:   CleanupBlockInfo CleanupInfo = PopCleanupBlock();
      81                 :   assert(CleanupInfo.CleanupBlock == Info.DtorBlock &&
                        0: branch 0 not taken
                       62: branch 1 taken
      82               62:          "Cleanup block mismatch!");
      83                 :   assert(!CleanupInfo.SwitchBlock &&
                        0: branch 0 not taken
                       62: branch 1 taken
      84               62:          "Should not have a switch block for temporary cleanup!");
      85                 :   assert(!CleanupInfo.EndBlock &&
                        0: branch 0 not taken
                       62: branch 1 taken
      86               62:          "Should not have an end block for temporary cleanup!");
      87                 : 
      88               62:   llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
                       62: branch 0 taken
                        0: branch 1 not taken
                       62: branch 3 taken
                        0: branch 4 not taken
                       62: branch 6 taken
                        0: branch 7 not taken
                       62: branch 8 taken
                        0: branch 9 not taken
      89               62:   if (CurBB && !CurBB->getTerminator() &&
      90                 :       Info.DtorBlock->getNumUses() == 0) {
      91               62:     CurBB->getInstList().splice(CurBB->end(), Info.DtorBlock->getInstList());
                       62: branch 0 taken
                        0: branch 1 not taken
      92               62:     delete Info.DtorBlock;
      93                 :   } else
      94                0:     EmitBlock(Info.DtorBlock);
      95                 : 
      96               62:   llvm::BasicBlock *CondEnd = 0;
      97                 : 
      98                 :   // If this is a conditional temporary, we need to check the condition
      99                 :   // boolean and only call the destructor if it's true.
                        9: branch 0 taken
                       53: branch 1 taken
     100               62:   if (Info.CondPtr) {
     101                9:     llvm::BasicBlock *CondBlock = createBasicBlock("cond.dtor.call");
     102                9:     CondEnd = createBasicBlock("cond.dtor.end");
     103                 : 
     104                9:     llvm::Value *Cond = Builder.CreateLoad(Info.CondPtr);
     105                9:     Builder.CreateCondBr(Cond, CondBlock, CondEnd);
     106                9:     EmitBlock(CondBlock);
     107                 :   }
     108                 : 
     109                 :   EmitCXXDestructorCall(Info.Temporary->getDestructor(),
     110               62:                         Dtor_Complete, Info.ThisPtr);
     111                 : 
                        9: branch 0 taken
                       53: branch 1 taken
     112               62:   if (CondEnd) {
     113                 :     // Reset the condition. to false.
     114                9:     Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), Info.CondPtr);
     115                9:     EmitBlock(CondEnd);
     116                 :   }
     117                 : 
     118               62:   LiveTemporaries.pop_back();
     119               62: }
     120                 : 
     121                 : RValue
     122                 : CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E,
     123                 :                                             llvm::Value *AggLoc,
     124                 :                                             bool IsAggLocVolatile,
     125               66:                                             bool IsInitializer) {
     126                 :   // Keep track of the current cleanup stack depth.
     127               66:   size_t CleanupStackDepth = CleanupEntries.size();
     128                 :   (void) CleanupStackDepth;
     129                 : 
     130               66:   unsigned OldNumLiveTemporaries = LiveTemporaries.size();
     131                 : 
     132                 :   RValue RV = EmitAnyExpr(E->getSubExpr(), AggLoc, IsAggLocVolatile,
     133               66:                           /*IgnoreResult=*/false, IsInitializer);
     134                 : 
     135                 :   // Pop temporaries.
                       52: branch 1 taken
                       66: branch 2 taken
     136              184:   while (LiveTemporaries.size() > OldNumLiveTemporaries)
     137               52:     PopCXXTemporary();
     138                 : 
     139                 :   assert(CleanupEntries.size() == CleanupStackDepth &&
                       66: branch 1 taken
                        0: branch 2 not taken
     140               66:          "Cleanup size mismatch!");
     141                 : 
     142                 :   return RV;
     143                 : }
     144                 : 
     145                 : LValue CodeGenFunction::EmitCXXExprWithTemporariesLValue(
     146                0:                                               const CXXExprWithTemporaries *E) {
     147                 :   // Keep track of the current cleanup stack depth.
     148                0:   size_t CleanupStackDepth = CleanupEntries.size();
     149                 :   (void) CleanupStackDepth;
     150                 : 
     151                0:   unsigned OldNumLiveTemporaries = LiveTemporaries.size();
     152                 : 
     153                0:   LValue LV = EmitLValue(E->getSubExpr());
     154                 : 
     155                 :   // Pop temporaries.
                        0: branch 1 not taken
                        0: branch 2 not taken
     156                0:   while (LiveTemporaries.size() > OldNumLiveTemporaries)
     157                0:     PopCXXTemporary();
     158                 : 
     159                 :   assert(CleanupEntries.size() == CleanupStackDepth &&
                        0: branch 1 not taken
                        0: branch 2 not taken
     160                0:          "Cleanup size mismatch!");
     161                 : 
     162                 :   return LV;
     163                 : }

Generated: 2010-02-10 01:31 by zcov