blob: f47af23f046b972141301818f0ad6a6fd20a6483 [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 =
Owen Andersonf48880a2009-07-21 02:57:15 +000032 new llvm::StoreInst(VMContext.getConstantIntFalse(), CondPtr);
Anders Carlsson8c0b2032009-06-04 02:47:33 +000033 llvm::BasicBlock *Block = AllocaInsertPt->getParent();
34 Block->getInstList().insertAfter((llvm::Instruction *)AllocaInsertPt, SI);
35
36 // Now set it to true.
Owen Andersonf48880a2009-07-21 02:57:15 +000037 Builder.CreateStore(VMContext.getConstantIntTrue(), CondPtr);
Anders Carlsson8c0b2032009-06-04 02:47:33 +000038 }
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.
Owen Andersonf48880a2009-07-21 02:57:15 +000077 Builder.CreateStore(VMContext.getConstantIntFalse(), Info.CondPtr);
Anders Carlsson8c0b2032009-06-04 02:47:33 +000078 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) {
Anders Carlssonf54741e2009-06-16 03:37:31 +000088 // 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
Anders Carlsson2ce66122009-06-03 18:40:21 +000093 // Keep track of the current cleanup stack depth.
94 size_t CleanupStackDepth = CleanupEntries.size();
Daniel Dunbarb4d4c4b2009-06-05 02:03:25 +000095 (void) CleanupStackDepth;
Anders Carlsson2ce66122009-06-03 18:40:21 +000096
97 unsigned OldNumLiveTemporaries = LiveTemporaries.size();
98
99 RValue RV = EmitAnyExpr(E->getSubExpr(), AggLoc, isAggLocVolatile);
100
Anders Carlsson8c0b2032009-06-04 02:47:33 +0000101 // Pop temporaries.
102 while (LiveTemporaries.size() > OldNumLiveTemporaries)
103 PopCXXTemporary();
Anders Carlsson2ce66122009-06-03 18:40:21 +0000104
Anders Carlsson8c0b2032009-06-04 02:47:33 +0000105 assert(CleanupEntries.size() == CleanupStackDepth &&
106 "Cleanup size mismatch!");
107
Anders Carlsson2ce66122009-06-03 18:40:21 +0000108 return RV;
109}
Anders Carlsson1d847502009-06-04 02:22:12 +0000110
111void
112CodeGenFunction::PushConditionalTempDestruction() {
113 // Store the current number of live temporaries.
114 ConditionalTempDestructionStack.push_back(LiveTemporaries.size());
115}
116
117void CodeGenFunction::PopConditionalTempDestruction() {
Anders Carlsson8c0b2032009-06-04 02:47:33 +0000118 size_t NumLiveTemporaries = ConditionalTempDestructionStack.back();
119 ConditionalTempDestructionStack.pop_back();
120
121 // Pop temporaries.
122 while (LiveTemporaries.size() > NumLiveTemporaries) {
Daniel Dunbarb4d4c4b2009-06-05 02:03:25 +0000123 assert(LiveTemporaries.back().CondPtr &&
124 "Conditional temporary must have a cond ptr!");
Anders Carlsson8c0b2032009-06-04 02:47:33 +0000125
126 PopCXXTemporary();
127 }
Anders Carlsson1d847502009-06-04 02:22:12 +0000128}
129