blob: d61884ce02afa6e0bffda02dc05a7d3b3ec019fa [file] [log] [blame]
Anders Carlsson756b5c42009-10-30 01:42:31 +00001//===--- CGException.cpp - Emit LLVM Code for C++ exceptions --------------===//
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++ exception related code generation.
11//
12//===----------------------------------------------------------------------===//
13
Mike Stump2bf701e2009-11-20 23:44:51 +000014#include "clang/AST/StmtCXX.h"
15
16#include "llvm/Intrinsics.h"
17
Anders Carlsson756b5c42009-10-30 01:42:31 +000018#include "CodeGenFunction.h"
19using namespace clang;
20using namespace CodeGen;
21
Anders Carlssond3379292009-10-30 02:27:02 +000022static llvm::Constant *getAllocateExceptionFn(CodeGenFunction &CGF) {
23 // void *__cxa_allocate_exception(size_t thrown_size);
24 const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType());
25 std::vector<const llvm::Type*> Args(1, SizeTy);
Mike Stump8755ec32009-12-10 00:06:18 +000026
27 const llvm::FunctionType *FTy =
Anders Carlssond3379292009-10-30 02:27:02 +000028 llvm::FunctionType::get(llvm::Type::getInt8PtrTy(CGF.getLLVMContext()),
29 Args, false);
Mike Stump8755ec32009-12-10 00:06:18 +000030
Anders Carlssond3379292009-10-30 02:27:02 +000031 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_allocate_exception");
32}
33
Mike Stump99533832009-12-02 07:41:41 +000034static llvm::Constant *getFreeExceptionFn(CodeGenFunction &CGF) {
35 // void __cxa_free_exception(void *thrown_exception);
36 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
37 std::vector<const llvm::Type*> Args(1, Int8PtrTy);
Mike Stump8755ec32009-12-10 00:06:18 +000038
39 const llvm::FunctionType *FTy =
Mike Stump99533832009-12-02 07:41:41 +000040 llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
41 Args, false);
Mike Stump8755ec32009-12-10 00:06:18 +000042
Mike Stump99533832009-12-02 07:41:41 +000043 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_free_exception");
44}
45
Anders Carlssond3379292009-10-30 02:27:02 +000046static llvm::Constant *getThrowFn(CodeGenFunction &CGF) {
Mike Stump8755ec32009-12-10 00:06:18 +000047 // void __cxa_throw(void *thrown_exception, std::type_info *tinfo,
Mike Stump99533832009-12-02 07:41:41 +000048 // void (*dest) (void *));
Anders Carlssond3379292009-10-30 02:27:02 +000049
50 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
51 std::vector<const llvm::Type*> Args(3, Int8PtrTy);
Mike Stump8755ec32009-12-10 00:06:18 +000052
53 const llvm::FunctionType *FTy =
Mike Stumpb4eea692009-11-20 00:56:31 +000054 llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
55 Args, false);
Mike Stump8755ec32009-12-10 00:06:18 +000056
Anders Carlssond3379292009-10-30 02:27:02 +000057 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_throw");
58}
59
Mike Stumpb4eea692009-11-20 00:56:31 +000060static llvm::Constant *getReThrowFn(CodeGenFunction &CGF) {
Mike Stump99533832009-12-02 07:41:41 +000061 // void __cxa_rethrow();
Mike Stumpb4eea692009-11-20 00:56:31 +000062
Mike Stump8755ec32009-12-10 00:06:18 +000063 const llvm::FunctionType *FTy =
Mike Stumpb4eea692009-11-20 00:56:31 +000064 llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false);
Mike Stump8755ec32009-12-10 00:06:18 +000065
Mike Stumpb4eea692009-11-20 00:56:31 +000066 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_rethrow");
67}
68
Mike Stump2bf701e2009-11-20 23:44:51 +000069static llvm::Constant *getBeginCatchFn(CodeGenFunction &CGF) {
Mike Stump99533832009-12-02 07:41:41 +000070 // void* __cxa_begin_catch();
Mike Stump2bf701e2009-11-20 23:44:51 +000071
72 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
73 std::vector<const llvm::Type*> Args(1, Int8PtrTy);
Mike Stump8755ec32009-12-10 00:06:18 +000074
75 const llvm::FunctionType *FTy =
Mike Stump0f590be2009-12-01 03:41:18 +000076 llvm::FunctionType::get(Int8PtrTy, Args, false);
Mike Stump8755ec32009-12-10 00:06:18 +000077
Mike Stump2bf701e2009-11-20 23:44:51 +000078 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch");
79}
80
81static llvm::Constant *getEndCatchFn(CodeGenFunction &CGF) {
Mike Stump99533832009-12-02 07:41:41 +000082 // void __cxa_end_catch();
Mike Stump2bf701e2009-11-20 23:44:51 +000083
Mike Stump8755ec32009-12-10 00:06:18 +000084 const llvm::FunctionType *FTy =
Mike Stump2bf701e2009-11-20 23:44:51 +000085 llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false);
Mike Stump8755ec32009-12-10 00:06:18 +000086
Mike Stump2bf701e2009-11-20 23:44:51 +000087 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch");
88}
89
Mike Stumpcce3d4f2009-12-07 23:38:24 +000090static llvm::Constant *getUnexpectedFn(CodeGenFunction &CGF) {
91 // void __cxa_call_unexepcted(void *thrown_exception);
92
93 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
94 std::vector<const llvm::Type*> Args(1, Int8PtrTy);
Mike Stump8755ec32009-12-10 00:06:18 +000095
96 const llvm::FunctionType *FTy =
Mike Stumpcce3d4f2009-12-07 23:38:24 +000097 llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
98 Args, false);
Mike Stump8755ec32009-12-10 00:06:18 +000099
Mike Stumpcce3d4f2009-12-07 23:38:24 +0000100 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_call_unexpected");
101}
102
Mike Stump0f590be2009-12-01 03:41:18 +0000103// FIXME: Eventually this will all go into the backend. Set from the target for
104// now.
105static int using_sjlj_exceptions = 0;
106
107static llvm::Constant *getUnwindResumeOrRethrowFn(CodeGenFunction &CGF) {
108 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
109 std::vector<const llvm::Type*> Args(1, Int8PtrTy);
Mike Stump8755ec32009-12-10 00:06:18 +0000110
111 const llvm::FunctionType *FTy =
Mike Stump0f590be2009-12-01 03:41:18 +0000112 llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), Args,
113 false);
Mike Stump8755ec32009-12-10 00:06:18 +0000114
Mike Stump0f590be2009-12-01 03:41:18 +0000115 if (using_sjlj_exceptions)
116 return CGF.CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume");
117 return CGF.CGM.CreateRuntimeFunction(FTy, "_Unwind_Resume_or_Rethrow");
118}
119
Mike Stump99533832009-12-02 07:41:41 +0000120static llvm::Constant *getTerminateFn(CodeGenFunction &CGF) {
121 // void __terminate();
122
Mike Stump8755ec32009-12-10 00:06:18 +0000123 const llvm::FunctionType *FTy =
Mike Stump99533832009-12-02 07:41:41 +0000124 llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false);
Mike Stump8755ec32009-12-10 00:06:18 +0000125
Mike Stump99533832009-12-02 07:41:41 +0000126 return CGF.CGM.CreateRuntimeFunction(FTy, "_ZSt9terminatev");
127}
128
Mike Stump0f590be2009-12-01 03:41:18 +0000129// CopyObject - Utility to copy an object. Calls copy constructor as necessary.
130// N is casted to the right type.
131static void CopyObject(CodeGenFunction &CGF, const Expr *E, llvm::Value *N) {
132 QualType ObjectType = E->getType();
133
134 // Store the throw exception in the exception object.
135 if (!CGF.hasAggregateLLVMType(ObjectType)) {
136 llvm::Value *Value = CGF.EmitScalarExpr(E);
137 const llvm::Type *ValuePtrTy = Value->getType()->getPointerTo(0);
Mike Stump8755ec32009-12-10 00:06:18 +0000138
Mike Stump0f590be2009-12-01 03:41:18 +0000139 CGF.Builder.CreateStore(Value, CGF.Builder.CreateBitCast(N, ValuePtrTy));
140 } else {
141 const llvm::Type *Ty = CGF.ConvertType(ObjectType)->getPointerTo(0);
142 const CXXRecordDecl *RD;
143 RD = cast<CXXRecordDecl>(ObjectType->getAs<RecordType>()->getDecl());
144 llvm::Value *This = CGF.Builder.CreateBitCast(N, Ty);
145 if (RD->hasTrivialCopyConstructor()) {
146 CGF.EmitAggExpr(E, This, false);
147 } else if (CXXConstructorDecl *CopyCtor
148 = RD->getCopyConstructor(CGF.getContext(), 0)) {
Mike Stump5030a982009-12-10 01:52:30 +0000149 llvm::BasicBlock *PrevLandingPad = CGF.getInvokeDest();
150 if (CGF.Exceptions) {
151 CodeGenFunction::EHCleanupBlock Cleanup(CGF);
Mike Stump99533832009-12-02 07:41:41 +0000152 llvm::Constant *FreeExceptionFn = getFreeExceptionFn(CGF);
153 const llvm::Type *Int8PtrTy
154 = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
155 llvm::Value *ExceptionPtr = CGF.Builder.CreateBitCast(N, Int8PtrTy);
156 CGF.Builder.CreateCall(FreeExceptionFn, ExceptionPtr);
157 }
Mike Stump5030a982009-12-10 01:52:30 +0000158
Mike Stump0f590be2009-12-01 03:41:18 +0000159 llvm::Value *Src = CGF.EmitLValue(E).getAddress();
Mike Stump5030a982009-12-10 01:52:30 +0000160 CGF.setInvokeDest(PrevLandingPad);
Mike Stump0f590be2009-12-01 03:41:18 +0000161
Mike Stump76958092009-12-09 23:31:35 +0000162 llvm::BasicBlock *TerminateHandler = CGF.getTerminateHandler();
Mike Stump5030a982009-12-10 01:52:30 +0000163 PrevLandingPad = CGF.getInvokeDest();
Mike Stump76958092009-12-09 23:31:35 +0000164 CGF.setInvokeDest(TerminateHandler);
165
Mike Stump0f590be2009-12-01 03:41:18 +0000166 // Stolen from EmitClassAggrMemberwiseCopy
167 llvm::Value *Callee = CGF.CGM.GetAddrOfCXXConstructor(CopyCtor,
168 Ctor_Complete);
169 CallArgList CallArgs;
170 CallArgs.push_back(std::make_pair(RValue::get(This),
171 CopyCtor->getThisType(CGF.getContext())));
172
173 // Push the Src ptr.
174 CallArgs.push_back(std::make_pair(RValue::get(Src),
175 CopyCtor->getParamDecl(0)->getType()));
176 QualType ResultType =
177 CopyCtor->getType()->getAs<FunctionType>()->getResultType();
178 CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
179 Callee, CallArgs, CopyCtor);
Mike Stump76958092009-12-09 23:31:35 +0000180 CGF.setInvokeDest(PrevLandingPad);
Mike Stump0f590be2009-12-01 03:41:18 +0000181 } else
Mike Stump99533832009-12-02 07:41:41 +0000182 llvm::llvm_unreachable("uncopyable object");
Mike Stump0f590be2009-12-01 03:41:18 +0000183 }
184}
185
186// CopyObject - Utility to copy an object. Calls copy constructor as necessary.
187// N is casted to the right type.
188static void CopyObject(CodeGenFunction &CGF, QualType ObjectType,
Mike Stumpd9cb7e92009-12-03 22:38:15 +0000189 bool WasPointer, llvm::Value *E, llvm::Value *N) {
Mike Stump0f590be2009-12-01 03:41:18 +0000190 // Store the throw exception in the exception object.
Mike Stumpb2debeb2009-12-08 01:29:31 +0000191 if (WasPointer || !CGF.hasAggregateLLVMType(ObjectType)) {
Mike Stump0f590be2009-12-01 03:41:18 +0000192 llvm::Value *Value = E;
Mike Stumpd9cb7e92009-12-03 22:38:15 +0000193 if (!WasPointer)
194 Value = CGF.Builder.CreateLoad(Value);
Mike Stump0f590be2009-12-01 03:41:18 +0000195 const llvm::Type *ValuePtrTy = Value->getType()->getPointerTo(0);
Mike Stump0f590be2009-12-01 03:41:18 +0000196 CGF.Builder.CreateStore(Value, CGF.Builder.CreateBitCast(N, ValuePtrTy));
197 } else {
198 const llvm::Type *Ty = CGF.ConvertType(ObjectType)->getPointerTo(0);
199 const CXXRecordDecl *RD;
200 RD = cast<CXXRecordDecl>(ObjectType->getAs<RecordType>()->getDecl());
201 llvm::Value *This = CGF.Builder.CreateBitCast(N, Ty);
202 if (RD->hasTrivialCopyConstructor()) {
203 CGF.EmitAggregateCopy(This, E, ObjectType);
204 } else if (CXXConstructorDecl *CopyCtor
205 = RD->getCopyConstructor(CGF.getContext(), 0)) {
Mike Stump0f590be2009-12-01 03:41:18 +0000206 llvm::Value *Src = E;
207
208 // Stolen from EmitClassAggrMemberwiseCopy
209 llvm::Value *Callee = CGF.CGM.GetAddrOfCXXConstructor(CopyCtor,
210 Ctor_Complete);
211 CallArgList CallArgs;
212 CallArgs.push_back(std::make_pair(RValue::get(This),
213 CopyCtor->getThisType(CGF.getContext())));
214
215 // Push the Src ptr.
216 CallArgs.push_back(std::make_pair(RValue::get(Src),
217 CopyCtor->getParamDecl(0)->getType()));
218 QualType ResultType =
219 CopyCtor->getType()->getAs<FunctionType>()->getResultType();
220 CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
221 Callee, CallArgs, CopyCtor);
Mike Stump0f590be2009-12-01 03:41:18 +0000222 } else
223 llvm::llvm_unreachable("uncopyable object");
224 }
225}
226
Anders Carlsson756b5c42009-10-30 01:42:31 +0000227void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) {
Anders Carlssond3379292009-10-30 02:27:02 +0000228 if (!E->getSubExpr()) {
Mike Stump0a3816e2009-12-04 01:51:45 +0000229 if (getInvokeDest()) {
230 llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
231 Builder.CreateInvoke(getReThrowFn(*this), Cont, getInvokeDest())
232 ->setDoesNotReturn();
233 EmitBlock(Cont);
234 } else
235 Builder.CreateCall(getReThrowFn(*this))->setDoesNotReturn();
Mike Stumpb4eea692009-11-20 00:56:31 +0000236 Builder.CreateUnreachable();
237
238 // Clear the insertion point to indicate we are in unreachable code.
239 Builder.ClearInsertionPoint();
Anders Carlssond3379292009-10-30 02:27:02 +0000240 return;
241 }
Mike Stump8755ec32009-12-10 00:06:18 +0000242
Anders Carlssond3379292009-10-30 02:27:02 +0000243 QualType ThrowType = E->getSubExpr()->getType();
Mike Stump8755ec32009-12-10 00:06:18 +0000244
Anders Carlssond3379292009-10-30 02:27:02 +0000245 // Now allocate the exception object.
246 const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
247 uint64_t TypeSize = getContext().getTypeSize(ThrowType) / 8;
Mike Stump8755ec32009-12-10 00:06:18 +0000248
Anders Carlssond3379292009-10-30 02:27:02 +0000249 llvm::Constant *AllocExceptionFn = getAllocateExceptionFn(*this);
Mike Stump8755ec32009-12-10 00:06:18 +0000250 llvm::Value *ExceptionPtr =
251 Builder.CreateCall(AllocExceptionFn,
Anders Carlssond3379292009-10-30 02:27:02 +0000252 llvm::ConstantInt::get(SizeTy, TypeSize),
253 "exception");
254
Mike Stump0f590be2009-12-01 03:41:18 +0000255 CopyObject(*this, E->getSubExpr(), ExceptionPtr);
Mike Stump8755ec32009-12-10 00:06:18 +0000256
Anders Carlssond3379292009-10-30 02:27:02 +0000257 // Now throw the exception.
258 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext());
Mike Stumpde050572009-12-02 18:57:08 +0000259 llvm::Constant *TypeInfo = CGM.GenerateRTTI(ThrowType);
Anders Carlssond3379292009-10-30 02:27:02 +0000260 llvm::Constant *Dtor = llvm::Constant::getNullValue(Int8PtrTy);
Mike Stump8755ec32009-12-10 00:06:18 +0000261
Mike Stump0a3816e2009-12-04 01:51:45 +0000262 if (getInvokeDest()) {
263 llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
Mike Stump8755ec32009-12-10 00:06:18 +0000264 llvm::InvokeInst *ThrowCall =
Mike Stump0a3816e2009-12-04 01:51:45 +0000265 Builder.CreateInvoke3(getThrowFn(*this), Cont, getInvokeDest(),
266 ExceptionPtr, TypeInfo, Dtor);
267 ThrowCall->setDoesNotReturn();
268 EmitBlock(Cont);
269 } else {
Mike Stump8755ec32009-12-10 00:06:18 +0000270 llvm::CallInst *ThrowCall =
Mike Stump0a3816e2009-12-04 01:51:45 +0000271 Builder.CreateCall3(getThrowFn(*this), ExceptionPtr, TypeInfo, Dtor);
272 ThrowCall->setDoesNotReturn();
273 }
Anders Carlssond3379292009-10-30 02:27:02 +0000274 Builder.CreateUnreachable();
Mike Stump8755ec32009-12-10 00:06:18 +0000275
Anders Carlssond3379292009-10-30 02:27:02 +0000276 // Clear the insertion point to indicate we are in unreachable code.
277 Builder.ClearInsertionPoint();
Mike Stumpc2ab4862009-12-07 20:12:14 +0000278
279 // FIXME: For now, emit a dummy basic block because expr emitters in generally
280 // are not ready to handle emitting expressions at unreachable points.
281 EnsureInsertPoint();
Anders Carlsson756b5c42009-10-30 01:42:31 +0000282}
Mike Stump2bf701e2009-11-20 23:44:51 +0000283
Mike Stumpcce3d4f2009-12-07 23:38:24 +0000284void CodeGenFunction::EmitStartEHSpec(const Decl *D) {
285 const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D);
286 if (FD == 0)
287 return;
288 const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>();
289 if (Proto == 0)
290 return;
291
292 assert(!Proto->hasAnyExceptionSpec() && "function with parameter pack");
293
294 if (!Proto->hasExceptionSpec())
295 return;
296
297 llvm::Constant *Personality =
298 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty
299 (VMContext),
300 true),
301 "__gxx_personality_v0");
302 Personality = llvm::ConstantExpr::getBitCast(Personality, PtrToInt8Ty);
303 llvm::Value *llvm_eh_exception =
304 CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
305 llvm::Value *llvm_eh_selector =
306 CGM.getIntrinsic(llvm::Intrinsic::eh_selector);
307 const llvm::IntegerType *Int8Ty;
308 const llvm::PointerType *PtrToInt8Ty;
309 Int8Ty = llvm::Type::getInt8Ty(VMContext);
310 // C string type. Used in lots of places.
311 PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty);
312 llvm::Constant *Null = llvm::ConstantPointerNull::get(PtrToInt8Ty);
313 llvm::SmallVector<llvm::Value*, 8> SelectorArgs;
314
315 llvm::BasicBlock *PrevLandingPad = getInvokeDest();
316 llvm::BasicBlock *EHSpecHandler = createBasicBlock("ehspec.handler");
317 llvm::BasicBlock *Match = createBasicBlock("match");
318 llvm::BasicBlock *Unwind = 0;
319
320 assert(PrevLandingPad == 0 && "EHSpec has invoke context");
321
322 llvm::BasicBlock *Cont = createBasicBlock("cont");
323
324 EmitBranchThroughCleanup(Cont);
325
326 // Emit the statements in the try {} block
327 setInvokeDest(EHSpecHandler);
328
329 EmitBlock(EHSpecHandler);
330 // Exception object
331 llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc");
332 llvm::Value *RethrowPtr = CreateTempAlloca(Exc->getType(), "_rethrow");
333
334 SelectorArgs.push_back(Exc);
335 SelectorArgs.push_back(Personality);
336 SelectorArgs.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
337 Proto->getNumExceptions()+1));
338
339 for (unsigned i = 0; i < Proto->getNumExceptions(); ++i) {
340 QualType Ty = Proto->getExceptionType(i);
341 llvm::Value *EHType
342 = CGM.GenerateRTTI(Ty.getNonReferenceType());
343 SelectorArgs.push_back(EHType);
344 }
345 if (Proto->getNumExceptions())
346 SelectorArgs.push_back(Null);
347
348 // Find which handler was matched.
349 llvm::Value *Selector
350 = Builder.CreateCall(llvm_eh_selector, SelectorArgs.begin(),
351 SelectorArgs.end(), "selector");
352 if (Proto->getNumExceptions()) {
353 Unwind = createBasicBlock("Unwind");
354
355 Builder.CreateStore(Exc, RethrowPtr);
356 Builder.CreateCondBr(Builder.CreateICmpSLT(Selector,
357 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
358 0)),
359 Match, Unwind);
360
361 EmitBlock(Match);
362 }
363 Builder.CreateCall(getUnexpectedFn(*this), Exc)->setDoesNotReturn();
364 Builder.CreateUnreachable();
365
366 if (Proto->getNumExceptions()) {
367 EmitBlock(Unwind);
368 Builder.CreateCall(getUnwindResumeOrRethrowFn(*this),
369 Builder.CreateLoad(RethrowPtr));
370 Builder.CreateUnreachable();
371 }
372
373 EmitBlock(Cont);
374}
375
376void CodeGenFunction::EmitEndEHSpec(const Decl *D) {
377 const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D);
378 if (FD == 0)
379 return;
380 const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>();
381 if (Proto == 0)
382 return;
383
384 if (!Proto->hasExceptionSpec())
385 return;
386
387 setInvokeDest(0);
388}
389
Mike Stump2bf701e2009-11-20 23:44:51 +0000390void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) {
Mike Stump2bf701e2009-11-20 23:44:51 +0000391 // Pointer to the personality function
392 llvm::Constant *Personality =
393 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty
394 (VMContext),
395 true),
396 "__gxx_personality_v0");
397 Personality = llvm::ConstantExpr::getBitCast(Personality, PtrToInt8Ty);
Mike Stump639787c2009-12-02 19:53:57 +0000398 llvm::Value *llvm_eh_exception =
399 CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
400 llvm::Value *llvm_eh_selector =
401 CGM.getIntrinsic(llvm::Intrinsic::eh_selector);
Mike Stump2bf701e2009-11-20 23:44:51 +0000402
Mike Stump2bf701e2009-11-20 23:44:51 +0000403 llvm::BasicBlock *PrevLandingPad = getInvokeDest();
404 llvm::BasicBlock *TryHandler = createBasicBlock("try.handler");
Mike Stump2bf701e2009-11-20 23:44:51 +0000405 llvm::BasicBlock *FinallyBlock = createBasicBlock("finally");
Mike Stump0f590be2009-12-01 03:41:18 +0000406 llvm::BasicBlock *FinallyRethrow = createBasicBlock("finally.throw");
Mike Stump2bf701e2009-11-20 23:44:51 +0000407 llvm::BasicBlock *FinallyEnd = createBasicBlock("finally.end");
408
409 // Push an EH context entry, used for handling rethrows.
410 PushCleanupBlock(FinallyBlock);
411
412 // Emit the statements in the try {} block
413 setInvokeDest(TryHandler);
414
Mike Stump6a1e0eb2009-12-04 23:26:17 +0000415 // FIXME: We should not have to do this here. The AST should have the member
416 // initializers under the CXXTryStmt's TryBlock.
417 if (OuterTryBlock == &S) {
418 GlobalDecl GD = CurGD;
419 const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
420
421 if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
422 size_t OldCleanupStackSize = CleanupEntries.size();
423 EmitCtorPrologue(CD, CurGD.getCtorType());
424 EmitStmt(S.getTryBlock());
425
426 // If any of the member initializers are temporaries bound to references
427 // make sure to emit their destructors.
428 EmitCleanupBlocks(OldCleanupStackSize);
429 } else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) {
430 llvm::BasicBlock *DtorEpilogue = createBasicBlock("dtor.epilogue");
431 PushCleanupBlock(DtorEpilogue);
432
433 EmitStmt(S.getTryBlock());
Mike Stump8755ec32009-12-10 00:06:18 +0000434
Mike Stump6a1e0eb2009-12-04 23:26:17 +0000435 CleanupBlockInfo Info = PopCleanupBlock();
436
437 assert(Info.CleanupBlock == DtorEpilogue && "Block mismatch!");
438 EmitBlock(DtorEpilogue);
439 EmitDtorEpilogue(DD, GD.getDtorType());
Mike Stump8755ec32009-12-10 00:06:18 +0000440
Mike Stump6a1e0eb2009-12-04 23:26:17 +0000441 if (Info.SwitchBlock)
442 EmitBlock(Info.SwitchBlock);
443 if (Info.EndBlock)
444 EmitBlock(Info.EndBlock);
Mike Stump8755ec32009-12-10 00:06:18 +0000445 } else
Mike Stump6a1e0eb2009-12-04 23:26:17 +0000446 EmitStmt(S.getTryBlock());
447 } else
448 EmitStmt(S.getTryBlock());
Mike Stump2bf701e2009-11-20 23:44:51 +0000449
450 // Jump to end if there is no exception
451 EmitBranchThroughCleanup(FinallyEnd);
452
Mike Stump9b39c512009-12-09 22:59:31 +0000453 llvm::BasicBlock *TerminateHandler = getTerminateHandler();
Mike Stump639787c2009-12-02 19:53:57 +0000454
Mike Stump2bf701e2009-11-20 23:44:51 +0000455 // Emit the handlers
456 EmitBlock(TryHandler);
Mike Stump8755ec32009-12-10 00:06:18 +0000457
Mike Stump2bf701e2009-11-20 23:44:51 +0000458 const llvm::IntegerType *Int8Ty;
459 const llvm::PointerType *PtrToInt8Ty;
460 Int8Ty = llvm::Type::getInt8Ty(VMContext);
461 // C string type. Used in lots of places.
462 PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty);
Mike Stump0f590be2009-12-01 03:41:18 +0000463 llvm::Constant *Null = llvm::ConstantPointerNull::get(PtrToInt8Ty);
464 llvm::SmallVector<llvm::Value*, 8> SelectorArgs;
Mike Stump0f590be2009-12-01 03:41:18 +0000465 llvm::Value *llvm_eh_typeid_for =
466 CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for);
Mike Stump2bf701e2009-11-20 23:44:51 +0000467 // Exception object
Mike Stump9b39c512009-12-09 22:59:31 +0000468 llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc");
Mike Stump0f590be2009-12-01 03:41:18 +0000469 llvm::Value *RethrowPtr = CreateTempAlloca(Exc->getType(), "_rethrow");
Mike Stump2bf701e2009-11-20 23:44:51 +0000470
Mike Stump9b39c512009-12-09 22:59:31 +0000471 llvm::SmallVector<llvm::Value*, 8> Args;
Mike Stump639787c2009-12-02 19:53:57 +0000472 Args.clear();
Mike Stump0f590be2009-12-01 03:41:18 +0000473 SelectorArgs.push_back(Exc);
474 SelectorArgs.push_back(Personality);
Mike Stump2bf701e2009-11-20 23:44:51 +0000475
Mike Stump0f590be2009-12-01 03:41:18 +0000476 bool HasCatchAll = false;
Mike Stump2bf701e2009-11-20 23:44:51 +0000477 for (unsigned i = 0; i<S.getNumHandlers(); ++i) {
478 const CXXCatchStmt *C = S.getHandler(i);
Mike Stump0f590be2009-12-01 03:41:18 +0000479 VarDecl *CatchParam = C->getExceptionDecl();
480 if (CatchParam) {
Mike Stumpde050572009-12-02 18:57:08 +0000481 llvm::Value *EHType
482 = CGM.GenerateRTTI(C->getCaughtType().getNonReferenceType());
Mike Stump0f590be2009-12-01 03:41:18 +0000483 SelectorArgs.push_back(EHType);
Mike Stump2bf701e2009-11-20 23:44:51 +0000484 } else {
485 // null indicates catch all
Mike Stump0f590be2009-12-01 03:41:18 +0000486 SelectorArgs.push_back(Null);
487 HasCatchAll = true;
Mike Stump2bf701e2009-11-20 23:44:51 +0000488 }
489 }
490
Mike Stump0f590be2009-12-01 03:41:18 +0000491 // We use a cleanup unless there was already a catch all.
492 if (!HasCatchAll) {
493 SelectorArgs.push_back(Null);
494 }
Mike Stump2bf701e2009-11-20 23:44:51 +0000495
Mike Stump0f590be2009-12-01 03:41:18 +0000496 // Find which handler was matched.
497 llvm::Value *Selector
498 = Builder.CreateCall(llvm_eh_selector, SelectorArgs.begin(),
499 SelectorArgs.end(), "selector");
Mike Stump2bf701e2009-11-20 23:44:51 +0000500 for (unsigned i = 0; i<S.getNumHandlers(); ++i) {
501 const CXXCatchStmt *C = S.getHandler(i);
Mike Stump0f590be2009-12-01 03:41:18 +0000502 VarDecl *CatchParam = C->getExceptionDecl();
503 Stmt *CatchBody = C->getHandlerBlock();
504
505 llvm::BasicBlock *Next = 0;
506
507 if (SelectorArgs[i+2] != Null) {
508 llvm::BasicBlock *Match = createBasicBlock("match");
509 Next = createBasicBlock("catch.next");
510 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext());
511 llvm::Value *Id
512 = Builder.CreateCall(llvm_eh_typeid_for,
513 Builder.CreateBitCast(SelectorArgs[i+2],
514 Int8PtrTy));
515 Builder.CreateCondBr(Builder.CreateICmpEQ(Selector, Id),
516 Match, Next);
517 EmitBlock(Match);
518 }
519
520 llvm::BasicBlock *MatchEnd = createBasicBlock("match.end");
521 llvm::BasicBlock *MatchHandler = createBasicBlock("match.handler");
522
523 PushCleanupBlock(MatchEnd);
524 setInvokeDest(MatchHandler);
525
526 llvm::Value *ExcObject = Builder.CreateCall(getBeginCatchFn(*this), Exc);
527
Mike Stumpf7f74672009-12-02 23:37:16 +0000528 {
529 CleanupScope CatchScope(*this);
530 // Bind the catch parameter if it exists.
531 if (CatchParam) {
532 QualType CatchType = CatchParam->getType().getNonReferenceType();
533 setInvokeDest(TerminateHandler);
Mike Stumpd9cb7e92009-12-03 22:38:15 +0000534 bool WasPointer = true;
535 if (!CatchType.getTypePtr()->isPointerType()) {
Mike Stump0a3816e2009-12-04 01:51:45 +0000536 if (!isa<ReferenceType>(CatchParam->getType()))
537 WasPointer = false;
Mike Stumpf7f74672009-12-02 23:37:16 +0000538 CatchType = getContext().getPointerType(CatchType);
Mike Stumpd9cb7e92009-12-03 22:38:15 +0000539 }
Mike Stumpf7f74672009-12-02 23:37:16 +0000540 ExcObject = Builder.CreateBitCast(ExcObject, ConvertType(CatchType));
Mike Stumpf7f74672009-12-02 23:37:16 +0000541 EmitLocalBlockVarDecl(*CatchParam);
Mike Stumpf668bd02009-12-03 03:40:14 +0000542 // FIXME: we need to do this sooner so that the EH region for the
543 // cleanup doesn't start until after the ctor completes, use a decl
544 // init?
Mike Stumpf7f74672009-12-02 23:37:16 +0000545 CopyObject(*this, CatchParam->getType().getNonReferenceType(),
Mike Stumpd9cb7e92009-12-03 22:38:15 +0000546 WasPointer, ExcObject, GetAddrOfLocalVar(CatchParam));
Mike Stumpf7f74672009-12-02 23:37:16 +0000547 setInvokeDest(MatchHandler);
548 }
549
550 EmitStmt(CatchBody);
Mike Stump0f590be2009-12-01 03:41:18 +0000551 }
552
Mike Stump0f590be2009-12-01 03:41:18 +0000553 EmitBranchThroughCleanup(FinallyEnd);
554
555 EmitBlock(MatchHandler);
556
557 llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc");
558 // We are required to emit this call to satisfy LLVM, even
559 // though we don't use the result.
Mike Stump639787c2009-12-02 19:53:57 +0000560 Args.clear();
Mike Stump0f590be2009-12-01 03:41:18 +0000561 Args.push_back(Exc);
562 Args.push_back(Personality);
563 Args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
564 0));
565 Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end());
566 Builder.CreateStore(Exc, RethrowPtr);
567 EmitBranchThroughCleanup(FinallyRethrow);
568
569 CodeGenFunction::CleanupBlockInfo Info = PopCleanupBlock();
570
571 EmitBlock(MatchEnd);
572
Mike Stump99533832009-12-02 07:41:41 +0000573 llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
Mike Stump0f590be2009-12-01 03:41:18 +0000574 Builder.CreateInvoke(getEndCatchFn(*this),
Mike Stump99533832009-12-02 07:41:41 +0000575 Cont, TerminateHandler,
Mike Stump0f590be2009-12-01 03:41:18 +0000576 Args.begin(), Args.begin());
Mike Stump0f590be2009-12-01 03:41:18 +0000577 EmitBlock(Cont);
578 if (Info.SwitchBlock)
579 EmitBlock(Info.SwitchBlock);
580 if (Info.EndBlock)
581 EmitBlock(Info.EndBlock);
582
Mike Stump0f590be2009-12-01 03:41:18 +0000583 Exc = Builder.CreateCall(llvm_eh_exception, "exc");
Mike Stump0f590be2009-12-01 03:41:18 +0000584 Builder.CreateStore(Exc, RethrowPtr);
585 EmitBranchThroughCleanup(FinallyRethrow);
586
587 if (Next)
588 EmitBlock(Next);
589 }
Mike Stumpa0867832009-12-04 19:03:47 +0000590 if (!HasCatchAll) {
591 Builder.CreateStore(Exc, RethrowPtr);
Mike Stump0f590be2009-12-01 03:41:18 +0000592 EmitBranchThroughCleanup(FinallyRethrow);
Mike Stumpa0867832009-12-04 19:03:47 +0000593 }
Mike Stump2bf701e2009-11-20 23:44:51 +0000594
595 CodeGenFunction::CleanupBlockInfo Info = PopCleanupBlock();
596
597 setInvokeDest(PrevLandingPad);
598
599 EmitBlock(FinallyBlock);
600
Mike Stump0f590be2009-12-01 03:41:18 +0000601 if (Info.SwitchBlock)
602 EmitBlock(Info.SwitchBlock);
603 if (Info.EndBlock)
604 EmitBlock(Info.EndBlock);
605
Mike Stump2bf701e2009-11-20 23:44:51 +0000606 // Branch around the rethrow code.
607 EmitBranch(FinallyEnd);
608
609 EmitBlock(FinallyRethrow);
Mike Stumpb2c9c0b2009-12-04 19:21:57 +0000610 // FIXME: Eventually we can chain the handlers together and just do a call
611 // here.
612 if (getInvokeDest()) {
613 llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
614 Builder.CreateInvoke(getUnwindResumeOrRethrowFn(*this), Cont,
615 getInvokeDest(),
616 Builder.CreateLoad(RethrowPtr));
617 EmitBlock(Cont);
618 } else
619 Builder.CreateCall(getUnwindResumeOrRethrowFn(*this),
620 Builder.CreateLoad(RethrowPtr));
621
Mike Stump2bf701e2009-11-20 23:44:51 +0000622 Builder.CreateUnreachable();
Mike Stump2bf701e2009-11-20 23:44:51 +0000623
624 EmitBlock(FinallyEnd);
Mike Stump2bf701e2009-11-20 23:44:51 +0000625}
Mike Stumpd88ea562009-12-09 03:35:49 +0000626
627CodeGenFunction::EHCleanupBlock::~EHCleanupBlock() {
628 llvm::BasicBlock *Cont1 = CGF.createBasicBlock("cont");
629 CGF.EmitBranch(Cont1);
630 CGF.setInvokeDest(PreviousInvokeDest);
631
632
633 CGF.EmitBlock(CleanupHandler);
634
635 llvm::Constant *Personality =
636 CGF.CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty
637 (CGF.VMContext),
638 true),
639 "__gxx_personality_v0");
640 Personality = llvm::ConstantExpr::getBitCast(Personality, CGF.PtrToInt8Ty);
641 llvm::Value *llvm_eh_exception =
642 CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
643 llvm::Value *llvm_eh_selector =
644 CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector);
645
646 llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc");
647 const llvm::IntegerType *Int8Ty;
648 const llvm::PointerType *PtrToInt8Ty;
649 Int8Ty = llvm::Type::getInt8Ty(CGF.VMContext);
650 // C string type. Used in lots of places.
651 PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty);
652 llvm::Constant *Null = llvm::ConstantPointerNull::get(PtrToInt8Ty);
653 llvm::SmallVector<llvm::Value*, 8> Args;
654 Args.clear();
655 Args.push_back(Exc);
656 Args.push_back(Personality);
657 Args.push_back(Null);
658 CGF.Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end());
659
660 CGF.EmitBlock(CleanupEntryBB);
661
662 CGF.EmitBlock(Cont1);
663
664 if (CGF.getInvokeDest()) {
665 llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont");
666 CGF.Builder.CreateInvoke(getUnwindResumeOrRethrowFn(CGF), Cont,
667 CGF.getInvokeDest(), Exc);
668 CGF.EmitBlock(Cont);
669 } else
670 CGF.Builder.CreateCall(getUnwindResumeOrRethrowFn(CGF), Exc);
671
672 CGF.Builder.CreateUnreachable();
673
674 CGF.EmitBlock(Cont);
675 if (CGF.Exceptions)
676 CGF.setInvokeDest(CleanupHandler);
677}
Mike Stump9b39c512009-12-09 22:59:31 +0000678
679llvm::BasicBlock *CodeGenFunction::getTerminateHandler() {
Mike Stump182f3832009-12-10 00:02:42 +0000680 if (TerminateHandler)
681 return TerminateHandler;
682
Mike Stump76958092009-12-09 23:31:35 +0000683 llvm::BasicBlock *Cont = 0;
684
685 if (HaveInsertPoint()) {
686 Cont = createBasicBlock("cont");
687 EmitBranch(Cont);
688 }
689
Mike Stump9b39c512009-12-09 22:59:31 +0000690 llvm::Constant *Personality =
691 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty
692 (VMContext),
693 true),
694 "__gxx_personality_v0");
695 Personality = llvm::ConstantExpr::getBitCast(Personality, PtrToInt8Ty);
696 llvm::Value *llvm_eh_exception =
697 CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
698 llvm::Value *llvm_eh_selector =
699 CGM.getIntrinsic(llvm::Intrinsic::eh_selector);
700
701 // Set up terminate handler
Mike Stump182f3832009-12-10 00:02:42 +0000702 TerminateHandler = createBasicBlock("terminate.handler");
Mike Stump9b39c512009-12-09 22:59:31 +0000703 EmitBlock(TerminateHandler);
704 llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc");
705 // We are required to emit this call to satisfy LLVM, even
706 // though we don't use the result.
707 llvm::SmallVector<llvm::Value*, 8> Args;
708 Args.push_back(Exc);
709 Args.push_back(Personality);
710 Args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
Mike Stump76958092009-12-09 23:31:35 +0000711 1));
Mike Stump9b39c512009-12-09 22:59:31 +0000712 Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end());
Mike Stump8755ec32009-12-10 00:06:18 +0000713 llvm::CallInst *TerminateCall =
Mike Stump9b39c512009-12-09 22:59:31 +0000714 Builder.CreateCall(getTerminateFn(*this));
715 TerminateCall->setDoesNotReturn();
716 TerminateCall->setDoesNotThrow();
717 Builder.CreateUnreachable();
718
719 // Clear the insertion point to indicate we are in unreachable code.
720 Builder.ClearInsertionPoint();
721
Mike Stump76958092009-12-09 23:31:35 +0000722 if (Cont)
723 EmitBlock(Cont);
724
Mike Stump9b39c512009-12-09 22:59:31 +0000725 return TerminateHandler;
726}