CGException.cpp revision ac418162692a951ca3796d6830496a85a2d12493
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
103static llvm::Constant *getUnwindResumeOrRethrowFn(CodeGenFunction &CGF) {
104  const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
105  std::vector<const llvm::Type*> Args(1, Int8PtrTy);
106
107  const llvm::FunctionType *FTy =
108    llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), Args,
109                            false);
110
111  if (CGF.CGM.getLangOptions().SjLjExceptions)
112    return CGF.CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume");
113  return CGF.CGM.CreateRuntimeFunction(FTy, "_Unwind_Resume_or_Rethrow");
114}
115
116static llvm::Constant *getTerminateFn(CodeGenFunction &CGF) {
117  // void __terminate();
118
119  const llvm::FunctionType *FTy =
120    llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false);
121
122  return CGF.CGM.CreateRuntimeFunction(FTy, "_ZSt9terminatev");
123}
124
125// Emits an exception expression into the given location.  This
126// differs from EmitAnyExprToMem only in that, if a final copy-ctor
127// call is required, an exception within that copy ctor causes
128// std::terminate to be invoked.
129static void EmitAnyExprToExn(CodeGenFunction &CGF, const Expr *E,
130                             llvm::Value *ExnLoc) {
131  // We want to release the allocated exception object if this
132  // expression throws.  We do this by pushing an EH-only cleanup
133  // block which, furthermore, deactivates itself after the expression
134  // is complete.
135  llvm::AllocaInst *ShouldFreeVar =
136    CGF.CreateTempAlloca(llvm::Type::getInt1Ty(CGF.getLLVMContext()),
137                         "should-free-exnobj.var");
138  CGF.InitTempAlloca(ShouldFreeVar,
139                     llvm::ConstantInt::getFalse(CGF.getLLVMContext()));
140
141  // A variable holding the exception pointer.  This is necessary
142  // because the throw expression does not necessarily dominate the
143  // cleanup, for example if it appears in a conditional expression.
144  llvm::AllocaInst *ExnLocVar =
145    CGF.CreateTempAlloca(ExnLoc->getType(), "exnobj.var");
146
147  llvm::BasicBlock *SavedInvokeDest = CGF.getInvokeDest();
148  {
149    CodeGenFunction::EHCleanupBlock Cleanup(CGF);
150    llvm::BasicBlock *FreeBB = CGF.createBasicBlock("free-exnobj");
151    llvm::BasicBlock *DoneBB = CGF.createBasicBlock("free-exnobj.done");
152
153    llvm::Value *ShouldFree = CGF.Builder.CreateLoad(ShouldFreeVar,
154                                                     "should-free-exnobj");
155    CGF.Builder.CreateCondBr(ShouldFree, FreeBB, DoneBB);
156    CGF.EmitBlock(FreeBB);
157    llvm::Value *ExnLocLocal = CGF.Builder.CreateLoad(ExnLocVar, "exnobj");
158    CGF.Builder.CreateCall(getFreeExceptionFn(CGF), ExnLocLocal);
159    CGF.EmitBlock(DoneBB);
160  }
161  llvm::BasicBlock *Cleanup = CGF.getInvokeDest();
162
163  CGF.Builder.CreateStore(ExnLoc, ExnLocVar);
164  CGF.Builder.CreateStore(llvm::ConstantInt::getTrue(CGF.getLLVMContext()),
165                          ShouldFreeVar);
166
167  // __cxa_allocate_exception returns a void*;  we need to cast this
168  // to the appropriate type for the object.
169  const llvm::Type *Ty = CGF.ConvertType(E->getType())->getPointerTo();
170  llvm::Value *TypedExnLoc = CGF.Builder.CreateBitCast(ExnLoc, Ty);
171
172  // FIXME: this isn't quite right!  If there's a final unelided call
173  // to a copy constructor, then according to [except.terminate]p1 we
174  // must call std::terminate() if that constructor throws, because
175  // technically that copy occurs after the exception expression is
176  // evaluated but before the exception is caught.  But the best way
177  // to handle that is to teach EmitAggExpr to do the final copy
178  // differently if it can't be elided.
179  CGF.EmitAnyExprToMem(E, TypedExnLoc, /*Volatile*/ false);
180
181  CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(CGF.getLLVMContext()),
182                          ShouldFreeVar);
183
184  // Pop the cleanup block if it's still the top of the cleanup stack.
185  // Otherwise, temporaries have been created and our cleanup will get
186  // properly removed in time.
187  // TODO: this is not very resilient.
188  if (CGF.getInvokeDest() == Cleanup)
189    CGF.setInvokeDest(SavedInvokeDest);
190}
191
192// CopyObject - Utility to copy an object.  Calls copy constructor as necessary.
193// N is casted to the right type.
194static void CopyObject(CodeGenFunction &CGF, QualType ObjectType,
195                       bool WasPointer, bool WasPointerReference,
196                       llvm::Value *E, llvm::Value *N) {
197  // Store the throw exception in the exception object.
198  if (WasPointer || !CGF.hasAggregateLLVMType(ObjectType)) {
199    llvm::Value *Value = E;
200    if (!WasPointer)
201      Value = CGF.Builder.CreateLoad(Value);
202    const llvm::Type *ValuePtrTy = Value->getType()->getPointerTo(0);
203    if (WasPointerReference) {
204      llvm::Value *Tmp = CGF.CreateTempAlloca(Value->getType(), "catch.param");
205      CGF.Builder.CreateStore(Value, Tmp);
206      Value = Tmp;
207      ValuePtrTy = Value->getType()->getPointerTo(0);
208    }
209    N = CGF.Builder.CreateBitCast(N, ValuePtrTy);
210    CGF.Builder.CreateStore(Value, N);
211  } else {
212    const llvm::Type *Ty = CGF.ConvertType(ObjectType)->getPointerTo(0);
213    const CXXRecordDecl *RD;
214    RD = cast<CXXRecordDecl>(ObjectType->getAs<RecordType>()->getDecl());
215    llvm::Value *This = CGF.Builder.CreateBitCast(N, Ty);
216    if (RD->hasTrivialCopyConstructor()) {
217      CGF.EmitAggregateCopy(This, E, ObjectType);
218    } else if (CXXConstructorDecl *CopyCtor
219               = RD->getCopyConstructor(CGF.getContext(), 0)) {
220      llvm::Value *Src = E;
221
222      // Stolen from EmitClassAggrMemberwiseCopy
223      llvm::Value *Callee = CGF.CGM.GetAddrOfCXXConstructor(CopyCtor,
224                                                            Ctor_Complete);
225      CallArgList CallArgs;
226      CallArgs.push_back(std::make_pair(RValue::get(This),
227                                      CopyCtor->getThisType(CGF.getContext())));
228
229      // Push the Src ptr.
230      CallArgs.push_back(std::make_pair(RValue::get(Src),
231                                        CopyCtor->getParamDecl(0)->getType()));
232
233      const FunctionProtoType *FPT
234        = CopyCtor->getType()->getAs<FunctionProtoType>();
235      CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(CallArgs, FPT),
236                   Callee, ReturnValueSlot(), CallArgs, CopyCtor);
237    } else
238      llvm_unreachable("uncopyable object");
239  }
240}
241
242void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) {
243  if (!E->getSubExpr()) {
244    if (getInvokeDest()) {
245      llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
246      Builder.CreateInvoke(getReThrowFn(*this), Cont, getInvokeDest())
247        ->setDoesNotReturn();
248      EmitBlock(Cont);
249    } else
250      Builder.CreateCall(getReThrowFn(*this))->setDoesNotReturn();
251    Builder.CreateUnreachable();
252
253    // Clear the insertion point to indicate we are in unreachable code.
254    Builder.ClearInsertionPoint();
255    return;
256  }
257
258  QualType ThrowType = E->getSubExpr()->getType();
259
260  // Now allocate the exception object.
261  const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
262  uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity();
263
264  llvm::Constant *AllocExceptionFn = getAllocateExceptionFn(*this);
265  llvm::Value *ExceptionPtr =
266    Builder.CreateCall(AllocExceptionFn,
267                       llvm::ConstantInt::get(SizeTy, TypeSize),
268                       "exception");
269
270  EmitAnyExprToExn(*this, E->getSubExpr(), ExceptionPtr);
271
272  // Now throw the exception.
273  const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext());
274  llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType);
275
276  // The address of the destructor.  If the exception type has a
277  // trivial destructor (or isn't a record), we just pass null.
278  llvm::Constant *Dtor = 0;
279  if (const RecordType *RecordTy = ThrowType->getAs<RecordType>()) {
280    CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl());
281    if (!Record->hasTrivialDestructor()) {
282      CXXDestructorDecl *DtorD = Record->getDestructor(getContext());
283      Dtor = CGM.GetAddrOfCXXDestructor(DtorD, Dtor_Complete);
284      Dtor = llvm::ConstantExpr::getBitCast(Dtor, Int8PtrTy);
285    }
286  }
287  if (!Dtor) Dtor = llvm::Constant::getNullValue(Int8PtrTy);
288
289  if (getInvokeDest()) {
290    llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
291    llvm::InvokeInst *ThrowCall =
292      Builder.CreateInvoke3(getThrowFn(*this), Cont, getInvokeDest(),
293                            ExceptionPtr, TypeInfo, Dtor);
294    ThrowCall->setDoesNotReturn();
295    EmitBlock(Cont);
296  } else {
297    llvm::CallInst *ThrowCall =
298      Builder.CreateCall3(getThrowFn(*this), ExceptionPtr, TypeInfo, Dtor);
299    ThrowCall->setDoesNotReturn();
300  }
301  Builder.CreateUnreachable();
302
303  // Clear the insertion point to indicate we are in unreachable code.
304  Builder.ClearInsertionPoint();
305
306  // FIXME: For now, emit a dummy basic block because expr emitters in generally
307  // are not ready to handle emitting expressions at unreachable points.
308  EnsureInsertPoint();
309}
310
311void CodeGenFunction::EmitStartEHSpec(const Decl *D) {
312  if (!Exceptions)
313    return;
314
315  const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D);
316  if (FD == 0)
317    return;
318  const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>();
319  if (Proto == 0)
320    return;
321
322  assert(!Proto->hasAnyExceptionSpec() && "function with parameter pack");
323
324  if (!Proto->hasExceptionSpec())
325    return;
326
327  llvm::Constant *Personality =
328    CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty
329                                                      (VMContext),
330                                                      true),
331                              "__gxx_personality_v0");
332  Personality = llvm::ConstantExpr::getBitCast(Personality, PtrToInt8Ty);
333  llvm::Value *llvm_eh_exception =
334    CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
335  llvm::Value *llvm_eh_selector =
336    CGM.getIntrinsic(llvm::Intrinsic::eh_selector);
337  const llvm::IntegerType *Int8Ty;
338  const llvm::PointerType *PtrToInt8Ty;
339  Int8Ty = llvm::Type::getInt8Ty(VMContext);
340  // C string type.  Used in lots of places.
341  PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty);
342  llvm::Constant *Null = llvm::ConstantPointerNull::get(PtrToInt8Ty);
343  llvm::SmallVector<llvm::Value*, 8> SelectorArgs;
344
345  llvm::BasicBlock *PrevLandingPad = getInvokeDest();
346  llvm::BasicBlock *EHSpecHandler = createBasicBlock("ehspec.handler");
347  llvm::BasicBlock *Match = createBasicBlock("match");
348  llvm::BasicBlock *Unwind = 0;
349
350  assert(PrevLandingPad == 0 && "EHSpec has invoke context");
351  (void)PrevLandingPad;
352
353  llvm::BasicBlock *Cont = createBasicBlock("cont");
354
355  EmitBranchThroughCleanup(Cont);
356
357  // Emit the statements in the try {} block
358  setInvokeDest(EHSpecHandler);
359
360  EmitBlock(EHSpecHandler);
361  // Exception object
362  llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc");
363  llvm::Value *RethrowPtr = CreateTempAlloca(Exc->getType(), "_rethrow");
364
365  SelectorArgs.push_back(Exc);
366  SelectorArgs.push_back(Personality);
367  SelectorArgs.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
368                                                Proto->getNumExceptions()+1));
369
370  for (unsigned i = 0; i < Proto->getNumExceptions(); ++i) {
371    QualType Ty = Proto->getExceptionType(i);
372    QualType ExceptType
373      = Ty.getNonReferenceType().getUnqualifiedType();
374    llvm::Value *EHType = CGM.GetAddrOfRTTIDescriptor(ExceptType);
375    SelectorArgs.push_back(EHType);
376  }
377  if (Proto->getNumExceptions())
378    SelectorArgs.push_back(Null);
379
380  // Find which handler was matched.
381  llvm::Value *Selector
382    = Builder.CreateCall(llvm_eh_selector, SelectorArgs.begin(),
383                         SelectorArgs.end(), "selector");
384  if (Proto->getNumExceptions()) {
385    Unwind = createBasicBlock("Unwind");
386
387    Builder.CreateStore(Exc, RethrowPtr);
388    Builder.CreateCondBr(Builder.CreateICmpSLT(Selector,
389                                               llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
390                                                                      0)),
391                         Match, Unwind);
392
393    EmitBlock(Match);
394  }
395  Builder.CreateCall(getUnexpectedFn(*this), Exc)->setDoesNotReturn();
396  Builder.CreateUnreachable();
397
398  if (Proto->getNumExceptions()) {
399    EmitBlock(Unwind);
400    Builder.CreateCall(getUnwindResumeOrRethrowFn(*this),
401                       Builder.CreateLoad(RethrowPtr));
402    Builder.CreateUnreachable();
403  }
404
405  EmitBlock(Cont);
406}
407
408void CodeGenFunction::EmitEndEHSpec(const Decl *D) {
409  if (!Exceptions)
410    return;
411
412  const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D);
413  if (FD == 0)
414    return;
415  const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>();
416  if (Proto == 0)
417    return;
418
419  if (!Proto->hasExceptionSpec())
420    return;
421
422  setInvokeDest(0);
423}
424
425void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) {
426  CXXTryStmtInfo Info = EnterCXXTryStmt(S);
427  EmitStmt(S.getTryBlock());
428  ExitCXXTryStmt(S, Info);
429}
430
431CodeGenFunction::CXXTryStmtInfo
432CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S) {
433  CXXTryStmtInfo Info;
434  Info.SavedLandingPad = getInvokeDest();
435  Info.HandlerBlock = createBasicBlock("try.handler");
436  Info.FinallyBlock = createBasicBlock("finally");
437
438  PushCleanupBlock(Info.FinallyBlock);
439  setInvokeDest(Info.HandlerBlock);
440
441  return Info;
442}
443
444void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S,
445                                     CXXTryStmtInfo TryInfo) {
446  // Pointer to the personality function
447  llvm::Constant *Personality =
448    CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty
449                                                      (VMContext),
450                                                      true),
451                              "__gxx_personality_v0");
452  Personality = llvm::ConstantExpr::getBitCast(Personality, PtrToInt8Ty);
453  llvm::Value *llvm_eh_exception =
454    CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
455  llvm::Value *llvm_eh_selector =
456    CGM.getIntrinsic(llvm::Intrinsic::eh_selector);
457
458  llvm::BasicBlock *PrevLandingPad = TryInfo.SavedLandingPad;
459  llvm::BasicBlock *TryHandler = TryInfo.HandlerBlock;
460  llvm::BasicBlock *FinallyBlock = TryInfo.FinallyBlock;
461  llvm::BasicBlock *FinallyRethrow = createBasicBlock("finally.throw");
462  llvm::BasicBlock *FinallyEnd = createBasicBlock("finally.end");
463
464  // Jump to end if there is no exception
465  EmitBranchThroughCleanup(FinallyEnd);
466
467  llvm::BasicBlock *TerminateHandler = getTerminateHandler();
468
469  // Emit the handlers
470  EmitBlock(TryHandler);
471
472  const llvm::IntegerType *Int8Ty;
473  const llvm::PointerType *PtrToInt8Ty;
474  Int8Ty = llvm::Type::getInt8Ty(VMContext);
475  // C string type.  Used in lots of places.
476  PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty);
477  llvm::Constant *Null = llvm::ConstantPointerNull::get(PtrToInt8Ty);
478  llvm::SmallVector<llvm::Value*, 8> SelectorArgs;
479  llvm::Value *llvm_eh_typeid_for =
480    CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for);
481  // Exception object
482  llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc");
483  llvm::Value *RethrowPtr = CreateTempAlloca(Exc->getType(), "_rethrow");
484
485  SelectorArgs.push_back(Exc);
486  SelectorArgs.push_back(Personality);
487
488  bool HasCatchAll = false;
489  for (unsigned i = 0; i<S.getNumHandlers(); ++i) {
490    const CXXCatchStmt *C = S.getHandler(i);
491    VarDecl *CatchParam = C->getExceptionDecl();
492    if (CatchParam) {
493      // C++ [except.handle]p3 indicates that top-level cv-qualifiers
494      // are ignored.
495      QualType CaughtType = C->getCaughtType().getNonReferenceType();
496      llvm::Value *EHTypeInfo
497        = CGM.GetAddrOfRTTIDescriptor(CaughtType.getUnqualifiedType());
498      SelectorArgs.push_back(EHTypeInfo);
499    } else {
500      // null indicates catch all
501      SelectorArgs.push_back(Null);
502      HasCatchAll = true;
503    }
504  }
505
506  // We use a cleanup unless there was already a catch all.
507  if (!HasCatchAll) {
508    SelectorArgs.push_back(Null);
509  }
510
511  // Find which handler was matched.
512  llvm::Value *Selector
513    = Builder.CreateCall(llvm_eh_selector, SelectorArgs.begin(),
514                         SelectorArgs.end(), "selector");
515  for (unsigned i = 0; i<S.getNumHandlers(); ++i) {
516    const CXXCatchStmt *C = S.getHandler(i);
517    VarDecl *CatchParam = C->getExceptionDecl();
518    Stmt *CatchBody = C->getHandlerBlock();
519
520    llvm::BasicBlock *Next = 0;
521
522    if (SelectorArgs[i+2] != Null) {
523      llvm::BasicBlock *Match = createBasicBlock("match");
524      Next = createBasicBlock("catch.next");
525      const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext());
526      llvm::Value *Id
527        = Builder.CreateCall(llvm_eh_typeid_for,
528                             Builder.CreateBitCast(SelectorArgs[i+2],
529                                                   Int8PtrTy));
530      Builder.CreateCondBr(Builder.CreateICmpEQ(Selector, Id),
531                           Match, Next);
532      EmitBlock(Match);
533    }
534
535    llvm::BasicBlock *MatchEnd = createBasicBlock("match.end");
536    llvm::BasicBlock *MatchHandler = createBasicBlock("match.handler");
537
538    PushCleanupBlock(MatchEnd);
539    setInvokeDest(MatchHandler);
540
541    llvm::Value *ExcObject = Builder.CreateCall(getBeginCatchFn(*this), Exc);
542
543    {
544      CleanupScope CatchScope(*this);
545      // Bind the catch parameter if it exists.
546      if (CatchParam) {
547        QualType CatchType = CatchParam->getType().getNonReferenceType();
548        setInvokeDest(TerminateHandler);
549        bool WasPointer = true;
550        bool WasPointerReference = false;
551        CatchType = CGM.getContext().getCanonicalType(CatchType);
552        if (CatchType.getTypePtr()->isPointerType()) {
553          if (isa<ReferenceType>(CatchParam->getType()))
554            WasPointerReference = true;
555        } else {
556          if (!isa<ReferenceType>(CatchParam->getType()))
557            WasPointer = false;
558          CatchType = getContext().getPointerType(CatchType);
559        }
560        ExcObject = Builder.CreateBitCast(ExcObject, ConvertType(CatchType));
561        EmitLocalBlockVarDecl(*CatchParam);
562        // FIXME: we need to do this sooner so that the EH region for the
563        // cleanup doesn't start until after the ctor completes, use a decl
564        // init?
565        CopyObject(*this, CatchParam->getType().getNonReferenceType(),
566                   WasPointer, WasPointerReference, ExcObject,
567                   GetAddrOfLocalVar(CatchParam));
568        setInvokeDest(MatchHandler);
569      }
570
571      EmitStmt(CatchBody);
572    }
573
574    EmitBranchThroughCleanup(FinallyEnd);
575
576    EmitBlock(MatchHandler);
577
578    llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc");
579    // We are required to emit this call to satisfy LLVM, even
580    // though we don't use the result.
581    llvm::Value *Args[] = {
582      Exc, Personality,
583      llvm::ConstantInt::getNullValue(llvm::Type::getInt32Ty(VMContext))
584    };
585    Builder.CreateCall(llvm_eh_selector, &Args[0], llvm::array_endof(Args));
586    Builder.CreateStore(Exc, RethrowPtr);
587    EmitBranchThroughCleanup(FinallyRethrow);
588
589    CodeGenFunction::CleanupBlockInfo Info = PopCleanupBlock();
590
591    EmitBlock(MatchEnd);
592
593    llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
594    Builder.CreateInvoke(getEndCatchFn(*this),
595                         Cont, TerminateHandler,
596                         &Args[0], &Args[0]);
597    EmitBlock(Cont);
598    if (Info.SwitchBlock)
599      EmitBlock(Info.SwitchBlock);
600    if (Info.EndBlock)
601      EmitBlock(Info.EndBlock);
602
603    Exc = Builder.CreateCall(llvm_eh_exception, "exc");
604    Builder.CreateStore(Exc, RethrowPtr);
605    EmitBranchThroughCleanup(FinallyRethrow);
606
607    if (Next)
608      EmitBlock(Next);
609  }
610  if (!HasCatchAll) {
611    Builder.CreateStore(Exc, RethrowPtr);
612    EmitBranchThroughCleanup(FinallyRethrow);
613  }
614
615  CodeGenFunction::CleanupBlockInfo Info = PopCleanupBlock();
616
617  setInvokeDest(PrevLandingPad);
618
619  EmitBlock(FinallyBlock);
620
621  if (Info.SwitchBlock)
622    EmitBlock(Info.SwitchBlock);
623  if (Info.EndBlock)
624    EmitBlock(Info.EndBlock);
625
626  // Branch around the rethrow code.
627  EmitBranch(FinallyEnd);
628
629  EmitBlock(FinallyRethrow);
630  // FIXME: Eventually we can chain the handlers together and just do a call
631  // here.
632  if (getInvokeDest()) {
633    llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
634    Builder.CreateInvoke(getUnwindResumeOrRethrowFn(*this), Cont,
635                         getInvokeDest(),
636                         Builder.CreateLoad(RethrowPtr));
637    EmitBlock(Cont);
638  } else
639    Builder.CreateCall(getUnwindResumeOrRethrowFn(*this),
640                       Builder.CreateLoad(RethrowPtr));
641
642  Builder.CreateUnreachable();
643
644  EmitBlock(FinallyEnd);
645}
646
647CodeGenFunction::EHCleanupBlock::~EHCleanupBlock() {
648  CGF.setInvokeDest(PreviousInvokeDest);
649
650  llvm::BasicBlock *EndOfCleanup = CGF.Builder.GetInsertBlock();
651
652  // Jump to the beginning of the cleanup.
653  CGF.Builder.SetInsertPoint(CleanupHandler, CleanupHandler->begin());
654
655  // The libstdc++ personality function.
656  // TODO: generalize to work with other libraries.
657  llvm::Constant *Personality =
658    CGF.CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty
659                                                          (CGF.VMContext),
660                                                          true),
661                                  "__gxx_personality_v0");
662  Personality = llvm::ConstantExpr::getBitCast(Personality, CGF.PtrToInt8Ty);
663
664  // %exception = call i8* @llvm.eh.exception()
665  //   Magic intrinsic which tells gives us a handle to the caught
666  //   exception.
667  llvm::Value *llvm_eh_exception =
668    CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
669  llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc");
670
671  llvm::Constant *Null = llvm::ConstantPointerNull::get(CGF.PtrToInt8Ty);
672
673  // %ignored = call i32 @llvm.eh.selector(i8* %exception,
674  //                                       i8* @__gxx_personality_v0,
675  //                                       i8* null)
676  //   Magic intrinsic which tells LLVM that this invoke landing pad is
677  //   just a cleanup block.
678  llvm::Value *Args[] = { Exc, Personality, Null };
679  llvm::Value *llvm_eh_selector =
680    CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector);
681  CGF.Builder.CreateCall(llvm_eh_selector, &Args[0], llvm::array_endof(Args));
682
683  // And then we fall through into the code that the user put there.
684  // Jump back to the end of the cleanup.
685  CGF.Builder.SetInsertPoint(EndOfCleanup);
686
687  // Rethrow the exception.
688  if (CGF.getInvokeDest()) {
689    llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont");
690    CGF.Builder.CreateInvoke(getUnwindResumeOrRethrowFn(CGF), Cont,
691                             CGF.getInvokeDest(), Exc);
692    CGF.EmitBlock(Cont);
693  } else
694    CGF.Builder.CreateCall(getUnwindResumeOrRethrowFn(CGF), Exc);
695  CGF.Builder.CreateUnreachable();
696
697  // Resume inserting where we started, but put the new cleanup
698  // handler in place.
699  CGF.Builder.SetInsertPoint(PreviousInsertionBlock);
700  if (CGF.Exceptions)
701    CGF.setInvokeDest(CleanupHandler);
702}
703
704llvm::BasicBlock *CodeGenFunction::getTerminateHandler() {
705  if (TerminateHandler)
706    return TerminateHandler;
707
708  // We don't want to change anything at the current location, so
709  // save it aside and clear the insert point.
710  llvm::BasicBlock *SavedInsertBlock = Builder.GetInsertBlock();
711  llvm::BasicBlock::iterator SavedInsertPoint = Builder.GetInsertPoint();
712  Builder.ClearInsertionPoint();
713
714  llvm::Constant *Personality =
715    CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty
716                                                      (VMContext),
717                                                      true),
718                              "__gxx_personality_v0");
719  Personality = llvm::ConstantExpr::getBitCast(Personality, PtrToInt8Ty);
720  llvm::Value *llvm_eh_exception =
721    CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
722  llvm::Value *llvm_eh_selector =
723    CGM.getIntrinsic(llvm::Intrinsic::eh_selector);
724
725  // Set up terminate handler
726  TerminateHandler = createBasicBlock("terminate.handler");
727  EmitBlock(TerminateHandler);
728  llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc");
729  // We are required to emit this call to satisfy LLVM, even
730  // though we don't use the result.
731  llvm::Value *Args[] = {
732    Exc, Personality,
733    llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1)
734  };
735  Builder.CreateCall(llvm_eh_selector, &Args[0], llvm::array_endof(Args));
736  llvm::CallInst *TerminateCall =
737    Builder.CreateCall(getTerminateFn(*this));
738  TerminateCall->setDoesNotReturn();
739  TerminateCall->setDoesNotThrow();
740  Builder.CreateUnreachable();
741
742  // Restore the saved insertion state.
743  Builder.SetInsertPoint(SavedInsertBlock, SavedInsertPoint);
744
745  return TerminateHandler;
746}
747