]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/CodeGen/CGCXXTemp.cpp
Update Clang sources to r73879.
[FreeBSD/FreeBSD.git] / lib / CodeGen / CGCXXTemp.cpp
1 //===--- CGCXXTemp.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                                        llvm::Value *Ptr) {
20   llvm::BasicBlock *DtorBlock = createBasicBlock("temp.dtor");
21   
22   llvm::Value *CondPtr = 0;
23   
24   // Check if temporaries need to be conditional. If so, we'll create a 
25   // condition boolean, initialize it to 0 and 
26   if (!ConditionalTempDestructionStack.empty()) {
27     CondPtr = CreateTempAlloca(llvm::Type::Int1Ty, "cond");
28   
29     // Initialize it to false. This initialization takes place right after
30     // the alloca insert point.
31     llvm::StoreInst *SI = 
32       new llvm::StoreInst(llvm::ConstantInt::getFalse(), CondPtr);
33     llvm::BasicBlock *Block = AllocaInsertPt->getParent();
34     Block->getInstList().insertAfter((llvm::Instruction *)AllocaInsertPt, SI);
35
36     // Now set it to true.
37     Builder.CreateStore(llvm::ConstantInt::getTrue(), CondPtr);
38   }
39   
40   LiveTemporaries.push_back(CXXLiveTemporaryInfo(Temporary, Ptr, DtorBlock, 
41                                                  CondPtr));
42
43   PushCleanupBlock(DtorBlock);
44 }
45
46 void CodeGenFunction::PopCXXTemporary() {
47   const CXXLiveTemporaryInfo& Info = LiveTemporaries.back();
48   
49   CleanupBlockInfo CleanupInfo = PopCleanupBlock();
50   assert(CleanupInfo.CleanupBlock == Info.DtorBlock && 
51          "Cleanup block mismatch!");
52   assert(!CleanupInfo.SwitchBlock && 
53          "Should not have a switch block for temporary cleanup!");
54   assert(!CleanupInfo.EndBlock && 
55          "Should not have an end block for temporary cleanup!");
56   
57   EmitBlock(Info.DtorBlock);
58
59   llvm::BasicBlock *CondEnd = 0;
60
61   // If this is a conditional temporary, we need to check the condition
62   // boolean and only call the destructor if it's true.
63   if (Info.CondPtr) {
64     llvm::BasicBlock *CondBlock = createBasicBlock("cond.dtor.call");
65     CondEnd = createBasicBlock("cond.dtor.end");
66       
67     llvm::Value *Cond = Builder.CreateLoad(Info.CondPtr);
68     Builder.CreateCondBr(Cond, CondBlock, CondEnd);
69     EmitBlock(CondBlock);
70   }
71   
72   EmitCXXDestructorCall(Info.Temporary->getDestructor(),
73                         Dtor_Complete, Info.ThisPtr);
74
75   if (CondEnd) {
76     // Reset the condition. to false.
77     Builder.CreateStore(llvm::ConstantInt::getFalse(), Info.CondPtr);
78     EmitBlock(CondEnd);
79   }
80   
81   LiveTemporaries.pop_back();
82 }
83
84 RValue
85 CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E,
86                                             llvm::Value *AggLoc,
87                                             bool isAggLocVolatile) {
88   // If we shouldn't destroy the temporaries, just emit the
89   // child expression.
90   if (!E->shouldDestroyTemporaries())
91     return EmitAnyExpr(E->getSubExpr(), AggLoc, isAggLocVolatile);
92
93   // Keep track of the current cleanup stack depth.
94   size_t CleanupStackDepth = CleanupEntries.size();
95   (void) CleanupStackDepth;
96
97   unsigned OldNumLiveTemporaries = LiveTemporaries.size();
98   
99   RValue RV = EmitAnyExpr(E->getSubExpr(), AggLoc, isAggLocVolatile);
100   
101   // Pop temporaries.
102   while (LiveTemporaries.size() > OldNumLiveTemporaries)
103     PopCXXTemporary();
104   
105   assert(CleanupEntries.size() == CleanupStackDepth &&
106          "Cleanup size mismatch!");
107   
108   return RV;
109 }
110
111 void 
112 CodeGenFunction::PushConditionalTempDestruction() {
113   // Store the current number of live temporaries.
114   ConditionalTempDestructionStack.push_back(LiveTemporaries.size());
115 }
116
117 void CodeGenFunction::PopConditionalTempDestruction() {
118  size_t NumLiveTemporaries = ConditionalTempDestructionStack.back();
119  ConditionalTempDestructionStack.pop_back();
120   
121   // Pop temporaries.
122   while (LiveTemporaries.size() > NumLiveTemporaries) {
123     assert(LiveTemporaries.back().CondPtr && 
124            "Conditional temporary must have a cond ptr!");
125
126     PopCXXTemporary();
127   }  
128 }
129