blob: bfce1b0f747b515925df21bd820fec3b8810381a [file] [log] [blame]
Anders Carlsson59486a22009-11-24 05:51:11 +00001//===--- CGTemporaries.cpp - Emit LLVM Code for C++ temporaries -----------===//
Anders Carlsson82aea732009-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 Stump11289f42009-09-09 15:08:12 +000018void CodeGenFunction::PushCXXTemporary(const CXXTemporary *Temporary,
Anders Carlsson82aea732009-06-03 18:40:21 +000019 llvm::Value *Ptr) {
Douglas Gregor4cd5d532009-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 Carlsson4c49bb92009-06-03 19:05:16 +000023 llvm::BasicBlock *DtorBlock = createBasicBlock("temp.dtor");
Mike Stump11289f42009-09-09 15:08:12 +000024
Anders Carlsson7d313fc2009-06-04 02:47:33 +000025 llvm::Value *CondPtr = 0;
Mike Stump11289f42009-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 Carlsson0a66c262009-11-20 17:27:56 +000029 if (ConditionalBranchLevel != 0) {
Owen Anderson41a75022009-08-13 21:57:51 +000030 CondPtr = CreateTempAlloca(llvm::Type::getInt1Ty(VMContext), "cond");
Mike Stump11289f42009-09-09 15:08:12 +000031
Anders Carlsson7d313fc2009-06-04 02:47:33 +000032 // Initialize it to false. This initialization takes place right after
33 // the alloca insert point.
Mike Stump11289f42009-09-09 15:08:12 +000034 llvm::StoreInst *SI =
Owen Andersonfe4e3472009-07-31 17:39:36 +000035 new llvm::StoreInst(llvm::ConstantInt::getFalse(VMContext), CondPtr);
Anders Carlsson7d313fc2009-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 Andersonfe4e3472009-07-31 17:39:36 +000040 Builder.CreateStore(llvm::ConstantInt::getTrue(VMContext), CondPtr);
Anders Carlsson7d313fc2009-06-04 02:47:33 +000041 }
Mike Stump11289f42009-09-09 15:08:12 +000042
43 LiveTemporaries.push_back(CXXLiveTemporaryInfo(Temporary, Ptr, DtorBlock,
Anders Carlsson7d313fc2009-06-04 02:47:33 +000044 CondPtr));
Anders Carlssonea89e2b2009-06-04 02:08:08 +000045
46 PushCleanupBlock(DtorBlock);
Mike Stumpcd8faeb2009-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 Carlsson82aea732009-06-03 18:40:21 +000074}
75
Anders Carlsson4c49bb92009-06-03 19:05:16 +000076void CodeGenFunction::PopCXXTemporary() {
77 const CXXLiveTemporaryInfo& Info = LiveTemporaries.back();
Mike Stump11289f42009-09-09 15:08:12 +000078
Anders Carlsson4c49bb92009-06-03 19:05:16 +000079 CleanupBlockInfo CleanupInfo = PopCleanupBlock();
Mike Stump11289f42009-09-09 15:08:12 +000080 assert(CleanupInfo.CleanupBlock == Info.DtorBlock &&
Anders Carlsson4c49bb92009-06-03 19:05:16 +000081 "Cleanup block mismatch!");
Mike Stump11289f42009-09-09 15:08:12 +000082 assert(!CleanupInfo.SwitchBlock &&
Anders Carlsson4c49bb92009-06-03 19:05:16 +000083 "Should not have a switch block for temporary cleanup!");
Mike Stump11289f42009-09-09 15:08:12 +000084 assert(!CleanupInfo.EndBlock &&
Anders Carlsson4c49bb92009-06-03 19:05:16 +000085 "Should not have an end block for temporary cleanup!");
Mike Stump11289f42009-09-09 15:08:12 +000086
Anders Carlssonaedb46f2009-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 Carlsson4c49bb92009-06-03 19:05:16 +000094
Anders Carlsson7d313fc2009-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 Stump11289f42009-09-09 15:08:12 +0000102
Anders Carlsson7d313fc2009-06-04 02:47:33 +0000103 llvm::Value *Cond = Builder.CreateLoad(Info.CondPtr);
104 Builder.CreateCondBr(Cond, CondBlock, CondEnd);
105 EmitBlock(CondBlock);
106 }
Mike Stump11289f42009-09-09 15:08:12 +0000107
Anders Carlsson4c49bb92009-06-03 19:05:16 +0000108 EmitCXXDestructorCall(Info.Temporary->getDestructor(),
109 Dtor_Complete, Info.ThisPtr);
110
Anders Carlsson7d313fc2009-06-04 02:47:33 +0000111 if (CondEnd) {
112 // Reset the condition. to false.
Owen Andersonfe4e3472009-07-31 17:39:36 +0000113 Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), Info.CondPtr);
Anders Carlsson7d313fc2009-06-04 02:47:33 +0000114 EmitBlock(CondEnd);
115 }
Mike Stump11289f42009-09-09 15:08:12 +0000116
Anders Carlsson4c49bb92009-06-03 19:05:16 +0000117 LiveTemporaries.pop_back();
118}
119
120RValue
Anders Carlsson82aea732009-06-03 18:40:21 +0000121CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E,
122 llvm::Value *AggLoc,
Anders Carlsson5b106a72009-08-16 07:36:22 +0000123 bool IsAggLocVolatile,
124 bool IsInitializer) {
Anders Carlsson82aea732009-06-03 18:40:21 +0000125 // Keep track of the current cleanup stack depth.
126 size_t CleanupStackDepth = CleanupEntries.size();
Daniel Dunbardd050562009-06-05 02:03:25 +0000127 (void) CleanupStackDepth;
Anders Carlsson82aea732009-06-03 18:40:21 +0000128
129 unsigned OldNumLiveTemporaries = LiveTemporaries.size();
Mike Stump11289f42009-09-09 15:08:12 +0000130
131 RValue RV = EmitAnyExpr(E->getSubExpr(), AggLoc, IsAggLocVolatile,
Anders Carlsson5b106a72009-08-16 07:36:22 +0000132 /*IgnoreResult=*/false, IsInitializer);
Mike Stump11289f42009-09-09 15:08:12 +0000133
Anders Carlsson7d313fc2009-06-04 02:47:33 +0000134 // Pop temporaries.
135 while (LiveTemporaries.size() > OldNumLiveTemporaries)
136 PopCXXTemporary();
Mike Stump11289f42009-09-09 15:08:12 +0000137
Anders Carlsson7d313fc2009-06-04 02:47:33 +0000138 assert(CleanupEntries.size() == CleanupStackDepth &&
139 "Cleanup size mismatch!");
Mike Stump11289f42009-09-09 15:08:12 +0000140
Anders Carlsson82aea732009-06-03 18:40:21 +0000141 return RV;
142}
Anders Carlsson44bfcf02009-06-04 02:22:12 +0000143
Anders Carlsson96bad9a2009-09-14 01:10:45 +0000144LValue CodeGenFunction::EmitCXXExprWithTemporariesLValue(
145 const CXXExprWithTemporaries *E) {
Anders Carlsson96bad9a2009-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}