blob: 4b7349e41c12fd646e51f892981bd9edfe5e2aba [file] [log] [blame]
Anders Carlsson2ce66122009-06-03 18:40:21 +00001//===--- 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"
15using namespace clang;
16using namespace CodeGen;
17
18void CodeGenFunction::PushCXXTemporary(const CXXTemporary *Temporary,
19 llvm::Value *Ptr) {
Anders Carlssonf4b8fea2009-06-03 19:05:16 +000020 llvm::BasicBlock *DtorBlock = createBasicBlock("temp.dtor");
Anders Carlsson8c0b2032009-06-04 02:47:33 +000021
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));
Anders Carlssond8bc5a92009-06-04 02:08:08 +000042
43 PushCleanupBlock(DtorBlock);
Anders Carlsson2ce66122009-06-03 18:40:21 +000044}
45
Anders Carlssonf4b8fea2009-06-03 19:05:16 +000046void 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
Anders Carlsson8c0b2032009-06-04 02:47:33 +000059 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
Anders Carlssonf4b8fea2009-06-03 19:05:16 +000072 EmitCXXDestructorCall(Info.Temporary->getDestructor(),
73 Dtor_Complete, Info.ThisPtr);
74
Anders Carlsson8c0b2032009-06-04 02:47:33 +000075 if (CondEnd) {
76 // Reset the condition. to false.
77 Builder.CreateStore(llvm::ConstantInt::getFalse(), Info.CondPtr);
78 EmitBlock(CondEnd);
79 }
80
Anders Carlssonf4b8fea2009-06-03 19:05:16 +000081 LiveTemporaries.pop_back();
82}
83
84RValue
Anders Carlsson2ce66122009-06-03 18:40:21 +000085CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E,
86 llvm::Value *AggLoc,
87 bool isAggLocVolatile) {
88 // Keep track of the current cleanup stack depth.
89 size_t CleanupStackDepth = CleanupEntries.size();
90
91 unsigned OldNumLiveTemporaries = LiveTemporaries.size();
92
93 RValue RV = EmitAnyExpr(E->getSubExpr(), AggLoc, isAggLocVolatile);
94
Anders Carlsson8c0b2032009-06-04 02:47:33 +000095 // Pop temporaries.
96 while (LiveTemporaries.size() > OldNumLiveTemporaries)
97 PopCXXTemporary();
Anders Carlsson2ce66122009-06-03 18:40:21 +000098
Anders Carlsson8c0b2032009-06-04 02:47:33 +000099 assert(CleanupEntries.size() == CleanupStackDepth &&
100 "Cleanup size mismatch!");
101
Anders Carlsson2ce66122009-06-03 18:40:21 +0000102 return RV;
103}
Anders Carlsson1d847502009-06-04 02:22:12 +0000104
105void
106CodeGenFunction::PushConditionalTempDestruction() {
107 // Store the current number of live temporaries.
108 ConditionalTempDestructionStack.push_back(LiveTemporaries.size());
109}
110
111void CodeGenFunction::PopConditionalTempDestruction() {
Anders Carlsson8c0b2032009-06-04 02:47:33 +0000112 size_t NumLiveTemporaries = ConditionalTempDestructionStack.back();
113 ConditionalTempDestructionStack.pop_back();
114
115 // Pop temporaries.
116 while (LiveTemporaries.size() > NumLiveTemporaries) {
117 const CXXLiveTemporaryInfo& TempInfo = LiveTemporaries.back();
118
119 assert(TempInfo.CondPtr && "Conditional temporary must have a cond ptr!");
120
121 PopCXXTemporary();
122 }
Anders Carlsson1d847502009-06-04 02:22:12 +0000123}
124