blob: bfce1b0f747b515925df21bd820fec3b8810381a [file] [log] [blame]
Anders Carlsson5b955922009-11-24 05:51:11 +00001//===--- CGTemporaries.cpp - Emit LLVM Code for C++ temporaries -----------===//
Anders Carlsson2ce66122009-06-03 18:40:21 +00002//
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
Mike Stump1eb44332009-09-09 15:08:12 +000018void CodeGenFunction::PushCXXTemporary(const CXXTemporary *Temporary,
Anders Carlsson2ce66122009-06-03 18:40:21 +000019 llvm::Value *Ptr) {
Douglas Gregor400fd3d2009-12-24 17:48:05 +000020 assert((LiveTemporaries.empty() ||
21 LiveTemporaries.back().ThisPtr != Ptr) &&
22 "Pushed the same temporary twice; AST is likely wrong");
Anders Carlssonf4b8fea2009-06-03 19:05:16 +000023 llvm::BasicBlock *DtorBlock = createBasicBlock("temp.dtor");
Mike Stump1eb44332009-09-09 15:08:12 +000024
Anders Carlsson8c0b2032009-06-04 02:47:33 +000025 llvm::Value *CondPtr = 0;
Mike Stump1eb44332009-09-09 15:08:12 +000026
27 // Check if temporaries need to be conditional. If so, we'll create a
28 // condition boolean, initialize it to 0 and
Anders Carlssona36bf8f2009-11-20 17:27:56 +000029 if (ConditionalBranchLevel != 0) {
Owen Anderson0032b272009-08-13 21:57:51 +000030 CondPtr = CreateTempAlloca(llvm::Type::getInt1Ty(VMContext), "cond");
Mike Stump1eb44332009-09-09 15:08:12 +000031
Anders Carlsson8c0b2032009-06-04 02:47:33 +000032 // Initialize it to false. This initialization takes place right after
33 // the alloca insert point.
Mike Stump1eb44332009-09-09 15:08:12 +000034 llvm::StoreInst *SI =
Owen Anderson3b144ba2009-07-31 17:39:36 +000035 new llvm::StoreInst(llvm::ConstantInt::getFalse(VMContext), CondPtr);
Anders Carlsson8c0b2032009-06-04 02:47:33 +000036 llvm::BasicBlock *Block = AllocaInsertPt->getParent();
37 Block->getInstList().insertAfter((llvm::Instruction *)AllocaInsertPt, SI);
38
39 // Now set it to true.
Owen Anderson3b144ba2009-07-31 17:39:36 +000040 Builder.CreateStore(llvm::ConstantInt::getTrue(VMContext), CondPtr);
Anders Carlsson8c0b2032009-06-04 02:47:33 +000041 }
Mike Stump1eb44332009-09-09 15:08:12 +000042
43 LiveTemporaries.push_back(CXXLiveTemporaryInfo(Temporary, Ptr, DtorBlock,
Anders Carlsson8c0b2032009-06-04 02:47:33 +000044 CondPtr));
Anders Carlssond8bc5a92009-06-04 02:08:08 +000045
46 PushCleanupBlock(DtorBlock);
Mike Stumpf2945c02009-12-17 06:08:47 +000047
48 if (Exceptions) {
49 const CXXLiveTemporaryInfo& Info = LiveTemporaries.back();
50 llvm::BasicBlock *CondEnd = 0;
51
52 EHCleanupBlock Cleanup(*this);
53
54 // If this is a conditional temporary, we need to check the condition
55 // boolean and only call the destructor if it's true.
56 if (Info.CondPtr) {
57 llvm::BasicBlock *CondBlock = createBasicBlock("cond.dtor.call");
58 CondEnd = createBasicBlock("cond.dtor.end");
59
60 llvm::Value *Cond = Builder.CreateLoad(Info.CondPtr);
61 Builder.CreateCondBr(Cond, CondBlock, CondEnd);
62 EmitBlock(CondBlock);
63 }
64
65 EmitCXXDestructorCall(Info.Temporary->getDestructor(),
66 Dtor_Complete, Info.ThisPtr);
67
68 if (CondEnd) {
69 // Reset the condition. to false.
70 Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), Info.CondPtr);
71 EmitBlock(CondEnd);
72 }
73 }
Anders Carlsson2ce66122009-06-03 18:40:21 +000074}
75
Anders Carlssonf4b8fea2009-06-03 19:05:16 +000076void CodeGenFunction::PopCXXTemporary() {
77 const CXXLiveTemporaryInfo& Info = LiveTemporaries.back();
Mike Stump1eb44332009-09-09 15:08:12 +000078
Anders Carlssonf4b8fea2009-06-03 19:05:16 +000079 CleanupBlockInfo CleanupInfo = PopCleanupBlock();
Mike Stump1eb44332009-09-09 15:08:12 +000080 assert(CleanupInfo.CleanupBlock == Info.DtorBlock &&
Anders Carlssonf4b8fea2009-06-03 19:05:16 +000081 "Cleanup block mismatch!");
Mike Stump1eb44332009-09-09 15:08:12 +000082 assert(!CleanupInfo.SwitchBlock &&
Anders Carlssonf4b8fea2009-06-03 19:05:16 +000083 "Should not have a switch block for temporary cleanup!");
Mike Stump1eb44332009-09-09 15:08:12 +000084 assert(!CleanupInfo.EndBlock &&
Anders Carlssonf4b8fea2009-06-03 19:05:16 +000085 "Should not have an end block for temporary cleanup!");
Mike Stump1eb44332009-09-09 15:08:12 +000086
Anders Carlsson283e4d52009-09-14 01:30:44 +000087 llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
88 if (CurBB && !CurBB->getTerminator() &&
89 Info.DtorBlock->getNumUses() == 0) {
90 CurBB->getInstList().splice(CurBB->end(), Info.DtorBlock->getInstList());
91 delete Info.DtorBlock;
92 } else
93 EmitBlock(Info.DtorBlock);
Anders Carlssonf4b8fea2009-06-03 19:05:16 +000094
Anders Carlsson8c0b2032009-06-04 02:47:33 +000095 llvm::BasicBlock *CondEnd = 0;
96
97 // If this is a conditional temporary, we need to check the condition
98 // boolean and only call the destructor if it's true.
99 if (Info.CondPtr) {
100 llvm::BasicBlock *CondBlock = createBasicBlock("cond.dtor.call");
101 CondEnd = createBasicBlock("cond.dtor.end");
Mike Stump1eb44332009-09-09 15:08:12 +0000102
Anders Carlsson8c0b2032009-06-04 02:47:33 +0000103 llvm::Value *Cond = Builder.CreateLoad(Info.CondPtr);
104 Builder.CreateCondBr(Cond, CondBlock, CondEnd);
105 EmitBlock(CondBlock);
106 }
Mike Stump1eb44332009-09-09 15:08:12 +0000107
Anders Carlssonf4b8fea2009-06-03 19:05:16 +0000108 EmitCXXDestructorCall(Info.Temporary->getDestructor(),
109 Dtor_Complete, Info.ThisPtr);
110
Anders Carlsson8c0b2032009-06-04 02:47:33 +0000111 if (CondEnd) {
112 // Reset the condition. to false.
Owen Anderson3b144ba2009-07-31 17:39:36 +0000113 Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), Info.CondPtr);
Anders Carlsson8c0b2032009-06-04 02:47:33 +0000114 EmitBlock(CondEnd);
115 }
Mike Stump1eb44332009-09-09 15:08:12 +0000116
Anders Carlssonf4b8fea2009-06-03 19:05:16 +0000117 LiveTemporaries.pop_back();
118}
119
120RValue
Anders Carlsson2ce66122009-06-03 18:40:21 +0000121CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E,
122 llvm::Value *AggLoc,
Anders Carlsson14c5cbf2009-08-16 07:36:22 +0000123 bool IsAggLocVolatile,
124 bool IsInitializer) {
Anders Carlsson2ce66122009-06-03 18:40:21 +0000125 // Keep track of the current cleanup stack depth.
126 size_t CleanupStackDepth = CleanupEntries.size();
Daniel Dunbarb4d4c4b2009-06-05 02:03:25 +0000127 (void) CleanupStackDepth;
Anders Carlsson2ce66122009-06-03 18:40:21 +0000128
129 unsigned OldNumLiveTemporaries = LiveTemporaries.size();
Mike Stump1eb44332009-09-09 15:08:12 +0000130
131 RValue RV = EmitAnyExpr(E->getSubExpr(), AggLoc, IsAggLocVolatile,
Anders Carlsson14c5cbf2009-08-16 07:36:22 +0000132 /*IgnoreResult=*/false, IsInitializer);
Mike Stump1eb44332009-09-09 15:08:12 +0000133
Anders Carlsson8c0b2032009-06-04 02:47:33 +0000134 // Pop temporaries.
135 while (LiveTemporaries.size() > OldNumLiveTemporaries)
136 PopCXXTemporary();
Mike Stump1eb44332009-09-09 15:08:12 +0000137
Anders Carlsson8c0b2032009-06-04 02:47:33 +0000138 assert(CleanupEntries.size() == CleanupStackDepth &&
139 "Cleanup size mismatch!");
Mike Stump1eb44332009-09-09 15:08:12 +0000140
Anders Carlsson2ce66122009-06-03 18:40:21 +0000141 return RV;
142}
Anders Carlsson1d847502009-06-04 02:22:12 +0000143
Anders Carlssonb9ea0b52009-09-14 01:10:45 +0000144LValue CodeGenFunction::EmitCXXExprWithTemporariesLValue(
145 const CXXExprWithTemporaries *E) {
Anders Carlssonb9ea0b52009-09-14 01:10:45 +0000146 // Keep track of the current cleanup stack depth.
147 size_t CleanupStackDepth = CleanupEntries.size();
148 (void) CleanupStackDepth;
149
150 unsigned OldNumLiveTemporaries = LiveTemporaries.size();
151
152 LValue LV = EmitLValue(E->getSubExpr());
153
154 // Pop temporaries.
155 while (LiveTemporaries.size() > OldNumLiveTemporaries)
156 PopCXXTemporary();
157
158 assert(CleanupEntries.size() == CleanupStackDepth &&
159 "Cleanup size mismatch!");
160
161 return LV;
162}