 |
|
 |
|
| 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 |
| |
 |
|
 |
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