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