1 //===--- 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 
14 #include "clang/AST/StmtCXX.h"
15 
16 #include "llvm/Intrinsics.h"
17 
18 #include "CodeGenFunction.h"
19 using namespace clang;
20 using namespace CodeGen;
21 
22 static 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);
26 
27   const llvm::FunctionType *FTy =
28   llvm::FunctionType::get(llvm::Type::getInt8PtrTy(CGF.getLLVMContext()),
29                           Args, false);
30 
31   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_allocate_exception");
32 }
33 
34 static 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);
38 
39   const llvm::FunctionType *FTy =
40   llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
41                           Args, false);
42 
43   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_free_exception");
44 }
45 
46 static llvm::Constant *getThrowFn(CodeGenFunction &CGF) {
47   // void __cxa_throw(void *thrown_exception, std::type_info *tinfo,
48   //                  void (*dest) (void *));
49 
50   const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
51   std::vector<const llvm::Type*> Args(3, Int8PtrTy);
52 
53   const llvm::FunctionType *FTy =
54     llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
55                             Args, false);
56 
57   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_throw");
58 }
59 
60 static llvm::Constant *getReThrowFn(CodeGenFunction &CGF) {
61   // void __cxa_rethrow();
62 
63   const llvm::FunctionType *FTy =
64     llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false);
65 
66   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_rethrow");
67 }
68 
69 static llvm::Constant *getBeginCatchFn(CodeGenFunction &CGF) {
70   // void* __cxa_begin_catch();
71 
72   const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
73   std::vector<const llvm::Type*> Args(1, Int8PtrTy);
74 
75   const llvm::FunctionType *FTy =
76     llvm::FunctionType::get(Int8PtrTy, Args, false);
77 
78   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch");
79 }
80 
81 static llvm::Constant *getEndCatchFn(CodeGenFunction &CGF) {
82   // void __cxa_end_catch();
83 
84   const llvm::FunctionType *FTy =
85     llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false);
86 
87   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch");
88 }
89 
90 static 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);
95 
96   const llvm::FunctionType *FTy =
97     llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
98                             Args, false);
99 
100   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_call_unexpected");
101 }
102 
103 // FIXME: Eventually this will all go into the backend.  Set from the target for
104 // now.
105 static int using_sjlj_exceptions = 0;
106 
107 static llvm::Constant *getUnwindResumeOrRethrowFn(CodeGenFunction &CGF) {
108   const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
109   std::vector<const llvm::Type*> Args(1, Int8PtrTy);
110 
111   const llvm::FunctionType *FTy =
112     llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), Args,
113                             false);
114 
115   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 
120 static llvm::Constant *getTerminateFn(CodeGenFunction &CGF) {
121   // void __terminate();
122 
123   const llvm::FunctionType *FTy =
124     llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false);
125 
126   return CGF.CGM.CreateRuntimeFunction(FTy, "_ZSt9terminatev");
127 }
128 
129 // CopyObject - Utility to copy an object.  Calls copy constructor as necessary.
130 // DestPtr is casted to the right type.
131 static void CopyObject(CodeGenFunction &CGF, const Expr *E,
132                        llvm::Value *DestPtr, llvm::Value *ExceptionPtrPtr) {
133   QualType ObjectType = E->getType();
134 
135   // Store the throw exception in the exception object.
136   if (!CGF.hasAggregateLLVMType(ObjectType)) {
137     llvm::Value *Value = CGF.EmitScalarExpr(E);
138     const llvm::Type *ValuePtrTy = Value->getType()->getPointerTo();
139 
140     CGF.Builder.CreateStore(Value,
141                             CGF.Builder.CreateBitCast(DestPtr, ValuePtrTy));
142   } else {
143     const llvm::Type *Ty = CGF.ConvertType(ObjectType)->getPointerTo();
144     const CXXRecordDecl *RD =
145       cast<CXXRecordDecl>(ObjectType->getAs<RecordType>()->getDecl());
146 
147     llvm::Value *This = CGF.Builder.CreateBitCast(DestPtr, Ty);
148     if (RD->hasTrivialCopyConstructor()) {
149       CGF.EmitAggExpr(E, This, false);
150     } else if (CXXConstructorDecl *CopyCtor
151                = RD->getCopyConstructor(CGF.getContext(), 0)) {
152       llvm::BasicBlock *PrevLandingPad = CGF.getInvokeDest();
153       if (CGF.Exceptions) {
154         CodeGenFunction::EHCleanupBlock Cleanup(CGF);
155         llvm::Constant *FreeExceptionFn = getFreeExceptionFn(CGF);
156 
157         // Load the exception pointer.
158         llvm::Value *ExceptionPtr = CGF.Builder.CreateLoad(ExceptionPtrPtr);
159         CGF.Builder.CreateCall(FreeExceptionFn, ExceptionPtr);
160       }
161 
162       llvm::Value *Src = CGF.EmitLValue(E).getAddress();
163       CGF.setInvokeDest(PrevLandingPad);
164 
165       llvm::BasicBlock *TerminateHandler = CGF.getTerminateHandler();
166       PrevLandingPad = CGF.getInvokeDest();
167       CGF.setInvokeDest(TerminateHandler);
168 
169       // Stolen from EmitClassAggrMemberwiseCopy
170       llvm::Value *Callee = CGF.CGM.GetAddrOfCXXConstructor(CopyCtor,
171                                                             Ctor_Complete);
172       CallArgList CallArgs;
173       CallArgs.push_back(std::make_pair(RValue::get(This),
174                                       CopyCtor->getThisType(CGF.getContext())));
175 
176       // Push the Src ptr.
177       CallArgs.push_back(std::make_pair(RValue::get(Src),
178                                         CopyCtor->getParamDecl(0)->getType()));
179       QualType ResultType =
180         CopyCtor->getType()->getAs<FunctionType>()->getResultType();
181       CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
182                    Callee, CallArgs, CopyCtor);
183       CGF.setInvokeDest(PrevLandingPad);
184     } else
185       llvm_unreachable("uncopyable object");
186   }
187 }
188 
189 // CopyObject - Utility to copy an object.  Calls copy constructor as necessary.
190 // N is casted to the right type.
191 static void CopyObject(CodeGenFunction &CGF, QualType ObjectType,
192                        bool WasPointer, llvm::Value *E, llvm::Value *N) {
193   // Store the throw exception in the exception object.
194   if (WasPointer || !CGF.hasAggregateLLVMType(ObjectType)) {
195     llvm::Value *Value = E;
196     if (!WasPointer)
197       Value = CGF.Builder.CreateLoad(Value);
198     const llvm::Type *ValuePtrTy = Value->getType()->getPointerTo(0);
199     CGF.Builder.CreateStore(Value, CGF.Builder.CreateBitCast(N, ValuePtrTy));
200   } else {
201     const llvm::Type *Ty = CGF.ConvertType(ObjectType)->getPointerTo(0);
202     const CXXRecordDecl *RD;
203     RD = cast<CXXRecordDecl>(ObjectType->getAs<RecordType>()->getDecl());
204     llvm::Value *This = CGF.Builder.CreateBitCast(N, Ty);
205     if (RD->hasTrivialCopyConstructor()) {
206       CGF.EmitAggregateCopy(This, E, ObjectType);
207     } else if (CXXConstructorDecl *CopyCtor
208                = RD->getCopyConstructor(CGF.getContext(), 0)) {
209       llvm::Value *Src = E;
210 
211       // Stolen from EmitClassAggrMemberwiseCopy
212       llvm::Value *Callee = CGF.CGM.GetAddrOfCXXConstructor(CopyCtor,
213                                                             Ctor_Complete);
214       CallArgList CallArgs;
215       CallArgs.push_back(std::make_pair(RValue::get(This),
216                                       CopyCtor->getThisType(CGF.getContext())));
217 
218       // Push the Src ptr.
219       CallArgs.push_back(std::make_pair(RValue::get(Src),
220                                         CopyCtor->getParamDecl(0)->getType()));
221       QualType ResultType =
222         CopyCtor->getType()->getAs<FunctionType>()->getResultType();
223       CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
224                    Callee, CallArgs, CopyCtor);
225     } else
226       llvm_unreachable("uncopyable object");
227   }
228 }
229 
230 void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) {
231   if (!E->getSubExpr()) {
232     if (getInvokeDest()) {
233       llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
234       Builder.CreateInvoke(getReThrowFn(*this), Cont, getInvokeDest())
235         ->setDoesNotReturn();
236       EmitBlock(Cont);
237     } else
238       Builder.CreateCall(getReThrowFn(*this))->setDoesNotReturn();
239     Builder.CreateUnreachable();
240 
241     // Clear the insertion point to indicate we are in unreachable code.
242     Builder.ClearInsertionPoint();
243     return;
244   }
245 
246   QualType ThrowType = E->getSubExpr()->getType();
247 
248   // Now allocate the exception object.
249   const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
250   uint64_t TypeSize = getContext().getTypeSize(ThrowType) / 8;
251 
252   llvm::Constant *AllocExceptionFn = getAllocateExceptionFn(*this);
253   llvm::Value *ExceptionPtr =
254     Builder.CreateCall(AllocExceptionFn,
255                        llvm::ConstantInt::get(SizeTy, TypeSize),
256                        "exception");
257 
258   llvm::Value *ExceptionPtrPtr =
259     CreateTempAlloca(ExceptionPtr->getType(), "exception.ptr");
260   Builder.CreateStore(ExceptionPtr, ExceptionPtrPtr);
261 
262 
263   CopyObject(*this, E->getSubExpr(), ExceptionPtr, ExceptionPtrPtr);
264 
265   // Now throw the exception.
266   const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext());
267   llvm::Constant *TypeInfo = CGM.GenerateRTTI(ThrowType);
268   llvm::Constant *Dtor = llvm::Constant::getNullValue(Int8PtrTy);
269 
270   if (getInvokeDest()) {
271     llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
272     llvm::InvokeInst *ThrowCall =
273       Builder.CreateInvoke3(getThrowFn(*this), Cont, getInvokeDest(),
274                             ExceptionPtr, TypeInfo, Dtor);
275     ThrowCall->setDoesNotReturn();
276     EmitBlock(Cont);
277   } else {
278     llvm::CallInst *ThrowCall =
279       Builder.CreateCall3(getThrowFn(*this), ExceptionPtr, TypeInfo, Dtor);
280     ThrowCall->setDoesNotReturn();
281   }
282   Builder.CreateUnreachable();
283 
284   // Clear the insertion point to indicate we are in unreachable code.
285   Builder.ClearInsertionPoint();
286 
287   // FIXME: For now, emit a dummy basic block because expr emitters in generally
288   // are not ready to handle emitting expressions at unreachable points.
289   EnsureInsertPoint();
290 }
291 
292 void CodeGenFunction::EmitStartEHSpec(const Decl *D) {
293   const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D);
294   if (FD == 0)
295     return;
296   const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>();
297   if (Proto == 0)
298     return;
299 
300   assert(!Proto->hasAnyExceptionSpec() && "function with parameter pack");
301 
302   if (!Proto->hasExceptionSpec())
303     return;
304 
305   llvm::Constant *Personality =
306     CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty
307                                                       (VMContext),
308                                                       true),
309                               "__gxx_personality_v0");
310   Personality = llvm::ConstantExpr::getBitCast(Personality, PtrToInt8Ty);
311   llvm::Value *llvm_eh_exception =
312     CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
313   llvm::Value *llvm_eh_selector =
314     CGM.getIntrinsic(llvm::Intrinsic::eh_selector);
315   const llvm::IntegerType *Int8Ty;
316   const llvm::PointerType *PtrToInt8Ty;
317   Int8Ty = llvm::Type::getInt8Ty(VMContext);
318   // C string type.  Used in lots of places.
319   PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty);
320   llvm::Constant *Null = llvm::ConstantPointerNull::get(PtrToInt8Ty);
321   llvm::SmallVector<llvm::Value*, 8> SelectorArgs;
322 
323   llvm::BasicBlock *PrevLandingPad = getInvokeDest();
324   llvm::BasicBlock *EHSpecHandler = createBasicBlock("ehspec.handler");
325   llvm::BasicBlock *Match = createBasicBlock("match");
326   llvm::BasicBlock *Unwind = 0;
327 
328   assert(PrevLandingPad == 0 && "EHSpec has invoke context");
329   (void)PrevLandingPad;
330 
331   llvm::BasicBlock *Cont = createBasicBlock("cont");
332 
333   EmitBranchThroughCleanup(Cont);
334 
335   // Emit the statements in the try {} block
336   setInvokeDest(EHSpecHandler);
337 
338   EmitBlock(EHSpecHandler);
339   // Exception object
340   llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc");
341   llvm::Value *RethrowPtr = CreateTempAlloca(Exc->getType(), "_rethrow");
342 
343   SelectorArgs.push_back(Exc);
344   SelectorArgs.push_back(Personality);
345   SelectorArgs.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
346                                                 Proto->getNumExceptions()+1));
347 
348   for (unsigned i = 0; i < Proto->getNumExceptions(); ++i) {
349     QualType Ty = Proto->getExceptionType(i);
350     llvm::Value *EHType
351       = CGM.GenerateRTTI(Ty.getNonReferenceType());
352     SelectorArgs.push_back(EHType);
353   }
354   if (Proto->getNumExceptions())
355     SelectorArgs.push_back(Null);
356 
357   // Find which handler was matched.
358   llvm::Value *Selector
359     = Builder.CreateCall(llvm_eh_selector, SelectorArgs.begin(),
360                          SelectorArgs.end(), "selector");
361   if (Proto->getNumExceptions()) {
362     Unwind = createBasicBlock("Unwind");
363 
364     Builder.CreateStore(Exc, RethrowPtr);
365     Builder.CreateCondBr(Builder.CreateICmpSLT(Selector,
366                                                llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
367                                                                       0)),
368                          Match, Unwind);
369 
370     EmitBlock(Match);
371   }
372   Builder.CreateCall(getUnexpectedFn(*this), Exc)->setDoesNotReturn();
373   Builder.CreateUnreachable();
374 
375   if (Proto->getNumExceptions()) {
376     EmitBlock(Unwind);
377     Builder.CreateCall(getUnwindResumeOrRethrowFn(*this),
378                        Builder.CreateLoad(RethrowPtr));
379     Builder.CreateUnreachable();
380   }
381 
382   EmitBlock(Cont);
383 }
384 
385 void CodeGenFunction::EmitEndEHSpec(const Decl *D) {
386   const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D);
387   if (FD == 0)
388     return;
389   const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>();
390   if (Proto == 0)
391     return;
392 
393   if (!Proto->hasExceptionSpec())
394     return;
395 
396   setInvokeDest(0);
397 }
398 
399 void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) {
400   // Pointer to the personality function
401   llvm::Constant *Personality =
402     CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty
403                                                       (VMContext),
404                                                       true),
405                               "__gxx_personality_v0");
406   Personality = llvm::ConstantExpr::getBitCast(Personality, PtrToInt8Ty);
407   llvm::Value *llvm_eh_exception =
408     CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
409   llvm::Value *llvm_eh_selector =
410     CGM.getIntrinsic(llvm::Intrinsic::eh_selector);
411 
412   llvm::BasicBlock *PrevLandingPad = getInvokeDest();
413   llvm::BasicBlock *TryHandler = createBasicBlock("try.handler");
414   llvm::BasicBlock *FinallyBlock = createBasicBlock("finally");
415   llvm::BasicBlock *FinallyRethrow = createBasicBlock("finally.throw");
416   llvm::BasicBlock *FinallyEnd = createBasicBlock("finally.end");
417 
418   // Push an EH context entry, used for handling rethrows.
419   PushCleanupBlock(FinallyBlock);
420 
421   // Emit the statements in the try {} block
422   setInvokeDest(TryHandler);
423 
424   // FIXME: We should not have to do this here.  The AST should have the member
425   // initializers under the CXXTryStmt's TryBlock.
426   if (OuterTryBlock == &S) {
427     GlobalDecl GD = CurGD;
428     const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
429 
430     if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
431       size_t OldCleanupStackSize = CleanupEntries.size();
432       EmitCtorPrologue(CD, CurGD.getCtorType());
433       EmitStmt(S.getTryBlock());
434 
435       // If any of the member initializers are temporaries bound to references
436       // make sure to emit their destructors.
437       EmitCleanupBlocks(OldCleanupStackSize);
438     } else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) {
439       llvm::BasicBlock *DtorEpilogue  = createBasicBlock("dtor.epilogue");
440       PushCleanupBlock(DtorEpilogue);
441 
442       EmitStmt(S.getTryBlock());
443 
444       CleanupBlockInfo Info = PopCleanupBlock();
445 
446       assert(Info.CleanupBlock == DtorEpilogue && "Block mismatch!");
447       EmitBlock(DtorEpilogue);
448       EmitDtorEpilogue(DD, GD.getDtorType());
449 
450       if (Info.SwitchBlock)
451         EmitBlock(Info.SwitchBlock);
452       if (Info.EndBlock)
453         EmitBlock(Info.EndBlock);
454     } else
455       EmitStmt(S.getTryBlock());
456   } else
457     EmitStmt(S.getTryBlock());
458 
459   // Jump to end if there is no exception
460   EmitBranchThroughCleanup(FinallyEnd);
461 
462   llvm::BasicBlock *TerminateHandler = getTerminateHandler();
463 
464   // Emit the handlers
465   EmitBlock(TryHandler);
466 
467   const llvm::IntegerType *Int8Ty;
468   const llvm::PointerType *PtrToInt8Ty;
469   Int8Ty = llvm::Type::getInt8Ty(VMContext);
470   // C string type.  Used in lots of places.
471   PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty);
472   llvm::Constant *Null = llvm::ConstantPointerNull::get(PtrToInt8Ty);
473   llvm::SmallVector<llvm::Value*, 8> SelectorArgs;
474   llvm::Value *llvm_eh_typeid_for =
475     CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for);
476   // Exception object
477   llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc");
478   llvm::Value *RethrowPtr = CreateTempAlloca(Exc->getType(), "_rethrow");
479 
480   llvm::SmallVector<llvm::Value*, 8> Args;
481   Args.clear();
482   SelectorArgs.push_back(Exc);
483   SelectorArgs.push_back(Personality);
484 
485   bool HasCatchAll = false;
486   for (unsigned i = 0; i<S.getNumHandlers(); ++i) {
487     const CXXCatchStmt *C = S.getHandler(i);
488     VarDecl *CatchParam = C->getExceptionDecl();
489     if (CatchParam) {
490       llvm::Value *EHType
491         = CGM.GenerateRTTI(C->getCaughtType().getNonReferenceType());
492       SelectorArgs.push_back(EHType);
493     } else {
494       // null indicates catch all
495       SelectorArgs.push_back(Null);
496       HasCatchAll = true;
497     }
498   }
499 
500   // We use a cleanup unless there was already a catch all.
501   if (!HasCatchAll) {
502     SelectorArgs.push_back(Null);
503   }
504 
505   // Find which handler was matched.
506   llvm::Value *Selector
507     = Builder.CreateCall(llvm_eh_selector, SelectorArgs.begin(),
508                          SelectorArgs.end(), "selector");
509   for (unsigned i = 0; i<S.getNumHandlers(); ++i) {
510     const CXXCatchStmt *C = S.getHandler(i);
511     VarDecl *CatchParam = C->getExceptionDecl();
512     Stmt *CatchBody = C->getHandlerBlock();
513 
514     llvm::BasicBlock *Next = 0;
515 
516     if (SelectorArgs[i+2] != Null) {
517       llvm::BasicBlock *Match = createBasicBlock("match");
518       Next = createBasicBlock("catch.next");
519       const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext());
520       llvm::Value *Id
521         = Builder.CreateCall(llvm_eh_typeid_for,
522                              Builder.CreateBitCast(SelectorArgs[i+2],
523                                                    Int8PtrTy));
524       Builder.CreateCondBr(Builder.CreateICmpEQ(Selector, Id),
525                            Match, Next);
526       EmitBlock(Match);
527     }
528 
529     llvm::BasicBlock *MatchEnd = createBasicBlock("match.end");
530     llvm::BasicBlock *MatchHandler = createBasicBlock("match.handler");
531 
532     PushCleanupBlock(MatchEnd);
533     setInvokeDest(MatchHandler);
534 
535     llvm::Value *ExcObject = Builder.CreateCall(getBeginCatchFn(*this), Exc);
536 
537     {
538       CleanupScope CatchScope(*this);
539       // Bind the catch parameter if it exists.
540       if (CatchParam) {
541         QualType CatchType = CatchParam->getType().getNonReferenceType();
542         setInvokeDest(TerminateHandler);
543         bool WasPointer = true;
544         if (!CatchType.getTypePtr()->isPointerType()) {
545           if (!isa<ReferenceType>(CatchParam->getType()))
546             WasPointer = false;
547           CatchType = getContext().getPointerType(CatchType);
548         }
549         ExcObject = Builder.CreateBitCast(ExcObject, ConvertType(CatchType));
550         EmitLocalBlockVarDecl(*CatchParam);
551         // FIXME: we need to do this sooner so that the EH region for the
552         // cleanup doesn't start until after the ctor completes, use a decl
553         // init?
554         CopyObject(*this, CatchParam->getType().getNonReferenceType(),
555                    WasPointer, ExcObject, GetAddrOfLocalVar(CatchParam));
556         setInvokeDest(MatchHandler);
557       }
558 
559       EmitStmt(CatchBody);
560     }
561 
562     EmitBranchThroughCleanup(FinallyEnd);
563 
564     EmitBlock(MatchHandler);
565 
566     llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc");
567     // We are required to emit this call to satisfy LLVM, even
568     // though we don't use the result.
569     Args.clear();
570     Args.push_back(Exc);
571     Args.push_back(Personality);
572     Args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
573                                           0));
574     Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end());
575     Builder.CreateStore(Exc, RethrowPtr);
576     EmitBranchThroughCleanup(FinallyRethrow);
577 
578     CodeGenFunction::CleanupBlockInfo Info = PopCleanupBlock();
579 
580     EmitBlock(MatchEnd);
581 
582     llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
583     Builder.CreateInvoke(getEndCatchFn(*this),
584                          Cont, TerminateHandler,
585                          Args.begin(), Args.begin());
586     EmitBlock(Cont);
587     if (Info.SwitchBlock)
588       EmitBlock(Info.SwitchBlock);
589     if (Info.EndBlock)
590       EmitBlock(Info.EndBlock);
591 
592     Exc = Builder.CreateCall(llvm_eh_exception, "exc");
593     Builder.CreateStore(Exc, RethrowPtr);
594     EmitBranchThroughCleanup(FinallyRethrow);
595 
596     if (Next)
597       EmitBlock(Next);
598   }
599   if (!HasCatchAll) {
600     Builder.CreateStore(Exc, RethrowPtr);
601     EmitBranchThroughCleanup(FinallyRethrow);
602   }
603 
604   CodeGenFunction::CleanupBlockInfo Info = PopCleanupBlock();
605 
606   setInvokeDest(PrevLandingPad);
607 
608   EmitBlock(FinallyBlock);
609 
610   if (Info.SwitchBlock)
611     EmitBlock(Info.SwitchBlock);
612   if (Info.EndBlock)
613     EmitBlock(Info.EndBlock);
614 
615   // Branch around the rethrow code.
616   EmitBranch(FinallyEnd);
617 
618   EmitBlock(FinallyRethrow);
619   // FIXME: Eventually we can chain the handlers together and just do a call
620   // here.
621   if (getInvokeDest()) {
622     llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
623     Builder.CreateInvoke(getUnwindResumeOrRethrowFn(*this), Cont,
624                          getInvokeDest(),
625                          Builder.CreateLoad(RethrowPtr));
626     EmitBlock(Cont);
627   } else
628     Builder.CreateCall(getUnwindResumeOrRethrowFn(*this),
629                        Builder.CreateLoad(RethrowPtr));
630 
631   Builder.CreateUnreachable();
632 
633   EmitBlock(FinallyEnd);
634 }
635 
636 CodeGenFunction::EHCleanupBlock::~EHCleanupBlock() {
637   llvm::BasicBlock *Cont1 = CGF.createBasicBlock("cont");
638   CGF.EmitBranch(Cont1);
639   CGF.setInvokeDest(PreviousInvokeDest);
640 
641 
642   CGF.EmitBlock(CleanupHandler);
643 
644   llvm::Constant *Personality =
645     CGF.CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty
646                                                           (CGF.VMContext),
647                                                           true),
648                                   "__gxx_personality_v0");
649   Personality = llvm::ConstantExpr::getBitCast(Personality, CGF.PtrToInt8Ty);
650   llvm::Value *llvm_eh_exception =
651     CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
652   llvm::Value *llvm_eh_selector =
653     CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector);
654 
655   llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc");
656   const llvm::IntegerType *Int8Ty;
657   const llvm::PointerType *PtrToInt8Ty;
658   Int8Ty = llvm::Type::getInt8Ty(CGF.VMContext);
659   // C string type.  Used in lots of places.
660   PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty);
661   llvm::Constant *Null = llvm::ConstantPointerNull::get(PtrToInt8Ty);
662   llvm::SmallVector<llvm::Value*, 8> Args;
663   Args.clear();
664   Args.push_back(Exc);
665   Args.push_back(Personality);
666   Args.push_back(Null);
667   CGF.Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end());
668 
669   CGF.EmitBlock(CleanupEntryBB);
670 
671   CGF.EmitBlock(Cont1);
672 
673   if (CGF.getInvokeDest()) {
674     llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont");
675     CGF.Builder.CreateInvoke(getUnwindResumeOrRethrowFn(CGF), Cont,
676                              CGF.getInvokeDest(), Exc);
677     CGF.EmitBlock(Cont);
678   } else
679     CGF.Builder.CreateCall(getUnwindResumeOrRethrowFn(CGF), Exc);
680 
681   CGF.Builder.CreateUnreachable();
682 
683   CGF.EmitBlock(Cont);
684   if (CGF.Exceptions)
685     CGF.setInvokeDest(CleanupHandler);
686 }
687 
688 llvm::BasicBlock *CodeGenFunction::getTerminateHandler() {
689   if (TerminateHandler)
690     return TerminateHandler;
691 
692   llvm::BasicBlock *Cont = 0;
693 
694   if (HaveInsertPoint()) {
695     Cont = createBasicBlock("cont");
696     EmitBranch(Cont);
697   }
698 
699   llvm::Constant *Personality =
700     CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty
701                                                       (VMContext),
702                                                       true),
703                               "__gxx_personality_v0");
704   Personality = llvm::ConstantExpr::getBitCast(Personality, PtrToInt8Ty);
705   llvm::Value *llvm_eh_exception =
706     CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
707   llvm::Value *llvm_eh_selector =
708     CGM.getIntrinsic(llvm::Intrinsic::eh_selector);
709 
710   // Set up terminate handler
711   TerminateHandler = createBasicBlock("terminate.handler");
712   EmitBlock(TerminateHandler);
713   llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc");
714   // We are required to emit this call to satisfy LLVM, even
715   // though we don't use the result.
716   llvm::SmallVector<llvm::Value*, 8> Args;
717   Args.push_back(Exc);
718   Args.push_back(Personality);
719   Args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
720                                         1));
721   Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end());
722   llvm::CallInst *TerminateCall =
723     Builder.CreateCall(getTerminateFn(*this));
724   TerminateCall->setDoesNotReturn();
725   TerminateCall->setDoesNotThrow();
726   Builder.CreateUnreachable();
727 
728   // Clear the insertion point to indicate we are in unreachable code.
729   Builder.ClearInsertionPoint();
730 
731   if (Cont)
732     EmitBlock(Cont);
733 
734   return TerminateHandler;
735 }
736