//===--- CGException.cpp - Emit LLVM Code for C++ exceptions --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This contains code dealing with C++ exception related code generation.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/StmtCXX.h"

#include "llvm/Intrinsics.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Support/CallSite.h"

#include "CGObjCRuntime.h"
#include "CodeGenFunction.h"
#include "CGException.h"
#include "TargetInfo.h"

using namespace clang;
using namespace CodeGen;

/// Push an entry of the given size onto this protected-scope stack.
char *EHScopeStack::allocate(size_t Size) {
  if (!StartOfBuffer) {
    unsigned Capacity = 1024;
    while (Capacity < Size) Capacity *= 2;
    StartOfBuffer = new char[Capacity];
    StartOfData = EndOfBuffer = StartOfBuffer + Capacity;
  } else if (static_cast<size_t>(StartOfData - StartOfBuffer) < Size) {
    unsigned CurrentCapacity = EndOfBuffer - StartOfBuffer;
    unsigned UsedCapacity = CurrentCapacity - (StartOfData - StartOfBuffer);

    unsigned NewCapacity = CurrentCapacity;
    do {
      NewCapacity *= 2;
    } while (NewCapacity < UsedCapacity + Size);

    char *NewStartOfBuffer = new char[NewCapacity];
    char *NewEndOfBuffer = NewStartOfBuffer + NewCapacity;
    char *NewStartOfData = NewEndOfBuffer - UsedCapacity;
    memcpy(NewStartOfData, StartOfData, UsedCapacity);
    delete [] StartOfBuffer;
    StartOfBuffer = NewStartOfBuffer;
    EndOfBuffer = NewEndOfBuffer;
    StartOfData = NewStartOfData;
  }

  assert(StartOfBuffer + Size <= StartOfData);
  StartOfData -= Size;
  return StartOfData;
}

EHScopeStack::stable_iterator
EHScopeStack::getEnclosingEHCleanup(iterator it) const {
  assert(it != end());
  do {
    if (isa<EHCleanupScope>(*it)) {
      if (cast<EHCleanupScope>(*it).isEHCleanup())
        return stabilize(it);
      return cast<EHCleanupScope>(*it).getEnclosingEHCleanup();
    }
    ++it;
  } while (it != end());
  return stable_end();
}


void *EHScopeStack::pushCleanup(CleanupKind Kind, size_t Size) {
  assert(((Size % sizeof(void*)) == 0) && "cleanup type is misaligned");
  char *Buffer = allocate(EHCleanupScope::getSizeForCleanupSize(Size));
  bool IsNormalCleanup = Kind & NormalCleanup;
  bool IsEHCleanup = Kind & EHCleanup;
  bool IsActive = !(Kind & InactiveCleanup);
  EHCleanupScope *Scope =
    new (Buffer) EHCleanupScope(IsNormalCleanup,
                                IsEHCleanup,
                                IsActive,
                                Size,
                                BranchFixups.size(),
                                InnermostNormalCleanup,
                                InnermostEHCleanup);
  if (IsNormalCleanup)
    InnermostNormalCleanup = stable_begin();
  if (IsEHCleanup)
    InnermostEHCleanup = stable_begin();

  return Scope->getCleanupBuffer();
}

void EHScopeStack::popCleanup() {
  assert(!empty() && "popping exception stack when not empty");

  assert(isa<EHCleanupScope>(*begin()));
  EHCleanupScope &Cleanup = cast<EHCleanupScope>(*begin());
  InnermostNormalCleanup = Cleanup.getEnclosingNormalCleanup();
  InnermostEHCleanup = Cleanup.getEnclosingEHCleanup();
  StartOfData += Cleanup.getAllocatedSize();

  if (empty()) NextEHDestIndex = FirstEHDestIndex;

  // Destroy the cleanup.
  Cleanup.~EHCleanupScope();

  // Check whether we can shrink the branch-fixups stack.
  if (!BranchFixups.empty()) {
    // If we no longer have any normal cleanups, all the fixups are
    // complete.
    if (!hasNormalCleanups())
      BranchFixups.clear();

    // Otherwise we can still trim out unnecessary nulls.
    else
      popNullFixups();
  }
}

EHFilterScope *EHScopeStack::pushFilter(unsigned NumFilters) {
  char *Buffer = allocate(EHFilterScope::getSizeForNumFilters(NumFilters));
  CatchDepth++;
  return new (Buffer) EHFilterScope(NumFilters);
}

void EHScopeStack::popFilter() {
  assert(!empty() && "popping exception stack when not empty");

  EHFilterScope &Filter = cast<EHFilterScope>(*begin());
  StartOfData += EHFilterScope::getSizeForNumFilters(Filter.getNumFilters());

  if (empty()) NextEHDestIndex = FirstEHDestIndex;

  assert(CatchDepth > 0 && "mismatched filter push/pop");
  CatchDepth--;
}

EHCatchScope *EHScopeStack::pushCatch(unsigned NumHandlers) {
  char *Buffer = allocate(EHCatchScope::getSizeForNumHandlers(NumHandlers));
  CatchDepth++;
  EHCatchScope *Scope = new (Buffer) EHCatchScope(NumHandlers);
  for (unsigned I = 0; I != NumHandlers; ++I)
    Scope->getHandlers()[I].Index = getNextEHDestIndex();
  return Scope;
}

void EHScopeStack::pushTerminate() {
  char *Buffer = allocate(EHTerminateScope::getSize());
  CatchDepth++;
  new (Buffer) EHTerminateScope(getNextEHDestIndex());
}

/// Remove any 'null' fixups on the stack.  However, we can't pop more
/// fixups than the fixup depth on the innermost normal cleanup, or
/// else fixups that we try to add to that cleanup will end up in the
/// wrong place.  We *could* try to shrink fixup depths, but that's
/// actually a lot of work for little benefit.
void EHScopeStack::popNullFixups() {
  // We expect this to only be called when there's still an innermost
  // normal cleanup;  otherwise there really shouldn't be any fixups.
  assert(hasNormalCleanups());

  EHScopeStack::iterator it = find(InnermostNormalCleanup);
  unsigned MinSize = cast<EHCleanupScope>(*it).getFixupDepth();
  assert(BranchFixups.size() >= MinSize && "fixup stack out of order");

  while (BranchFixups.size() > MinSize &&
         BranchFixups.back().Destination == 0)
    BranchFixups.pop_back();
}

static llvm::Constant *getAllocateExceptionFn(CodeGenFunction &CGF) {
  // void *__cxa_allocate_exception(size_t thrown_size);
  const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType());
  std::vector<const llvm::Type*> Args(1, SizeTy);

  const llvm::FunctionType *FTy =
  llvm::FunctionType::get(llvm::Type::getInt8PtrTy(CGF.getLLVMContext()),
                          Args, false);

  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_allocate_exception");
}

static llvm::Constant *getFreeExceptionFn(CodeGenFunction &CGF) {
  // void __cxa_free_exception(void *thrown_exception);
  const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
  std::vector<const llvm::Type*> Args(1, Int8PtrTy);

  const llvm::FunctionType *FTy =
  llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
                          Args, false);

  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_free_exception");
}

static llvm::Constant *getThrowFn(CodeGenFunction &CGF) {
  // void __cxa_throw(void *thrown_exception, std::type_info *tinfo,
  //                  void (*dest) (void *));

  const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
  std::vector<const llvm::Type*> Args(3, Int8PtrTy);

  const llvm::FunctionType *FTy =
    llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
                            Args, false);

  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_throw");
}

static llvm::Constant *getReThrowFn(CodeGenFunction &CGF) {
  // void __cxa_rethrow();

  const llvm::FunctionType *FTy =
    llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false);

  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_rethrow");
}

static llvm::Constant *getGetExceptionPtrFn(CodeGenFunction &CGF) {
  // void *__cxa_get_exception_ptr(void*);
  const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
  std::vector<const llvm::Type*> Args(1, Int8PtrTy);

  const llvm::FunctionType *FTy =
    llvm::FunctionType::get(Int8PtrTy, Args, false);

  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_get_exception_ptr");
}

static llvm::Constant *getBeginCatchFn(CodeGenFunction &CGF) {
  // void *__cxa_begin_catch(void*);

  const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
  std::vector<const llvm::Type*> Args(1, Int8PtrTy);

  const llvm::FunctionType *FTy =
    llvm::FunctionType::get(Int8PtrTy, Args, false);

  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch");
}

static llvm::Constant *getEndCatchFn(CodeGenFunction &CGF) {
  // void __cxa_end_catch();

  const llvm::FunctionType *FTy =
    llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false);

  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch");
}

static llvm::Constant *getUnexpectedFn(CodeGenFunction &CGF) {
  // void __cxa_call_unexepcted(void *thrown_exception);

  const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
  std::vector<const llvm::Type*> Args(1, Int8PtrTy);

  const llvm::FunctionType *FTy =
    llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()),
                            Args, false);

  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_call_unexpected");
}

llvm::Constant *CodeGenFunction::getUnwindResumeOrRethrowFn() {
  const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext());
  std::vector<const llvm::Type*> Args(1, Int8PtrTy);

  const llvm::FunctionType *FTy =
    llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()), Args,
                            false);

  if (CGM.getLangOptions().SjLjExceptions)
    return CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume_or_Rethrow");
  return CGM.CreateRuntimeFunction(FTy, "_Unwind_Resume_or_Rethrow");
}

static llvm::Constant *getTerminateFn(CodeGenFunction &CGF) {
  // void __terminate();

  const llvm::FunctionType *FTy =
    llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false);

  return CGF.CGM.CreateRuntimeFunction(FTy, 
      CGF.CGM.getLangOptions().CPlusPlus ? "_ZSt9terminatev" : "abort");
}

static llvm::Constant *getCatchallRethrowFn(CodeGenFunction &CGF,
                                            llvm::StringRef Name) {
  const llvm::Type *Int8PtrTy =
    llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
  std::vector<const llvm::Type*> Args(1, Int8PtrTy);

  const llvm::Type *VoidTy = llvm::Type::getVoidTy(CGF.getLLVMContext());
  const llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, Args, false);

  return CGF.CGM.CreateRuntimeFunction(FTy, Name);
}

const EHPersonality EHPersonality::GNU_C("__gcc_personality_v0");
const EHPersonality EHPersonality::GNU_C_SJLJ("__gcc_personality_sj0");
const EHPersonality EHPersonality::NeXT_ObjC("__objc_personality_v0");
const EHPersonality EHPersonality::GNU_CPlusPlus("__gxx_personality_v0");
const EHPersonality EHPersonality::GNU_CPlusPlus_SJLJ("__gxx_personality_sj0");
const EHPersonality EHPersonality::GNU_ObjC("__gnu_objc_personality_v0",
                                            "objc_exception_throw");

static const EHPersonality &getCPersonality(const LangOptions &L) {
  if (L.SjLjExceptions)
    return EHPersonality::GNU_C_SJLJ;
  return EHPersonality::GNU_C;
}

static const EHPersonality &getObjCPersonality(const LangOptions &L) {
  if (L.NeXTRuntime) {
    if (L.ObjCNonFragileABI) return EHPersonality::NeXT_ObjC;
    else return getCPersonality(L);
  } else {
    return EHPersonality::GNU_ObjC;
  }
}

static const EHPersonality &getCXXPersonality(const LangOptions &L) {
  if (L.SjLjExceptions)
    return EHPersonality::GNU_CPlusPlus_SJLJ;
  else
    return EHPersonality::GNU_CPlusPlus;
}

/// Determines the personality function to use when both C++
/// and Objective-C exceptions are being caught.
static const EHPersonality &getObjCXXPersonality(const LangOptions &L) {
  // The ObjC personality defers to the C++ personality for non-ObjC
  // handlers.  Unlike the C++ case, we use the same personality
  // function on targets using (backend-driven) SJLJ EH.
  if (L.NeXTRuntime) {
    if (L.ObjCNonFragileABI)
      return EHPersonality::NeXT_ObjC;

    // In the fragile ABI, just use C++ exception handling and hope
    // they're not doing crazy exception mixing.
    else
      return getCXXPersonality(L);
  }

  // The GNU runtime's personality function inherently doesn't support
  // mixed EH.  Use the C++ personality just to avoid returning null.
  return getCXXPersonality(L);
}

const EHPersonality &EHPersonality::get(const LangOptions &L) {
  if (L.CPlusPlus && L.ObjC1)
    return getObjCXXPersonality(L);
  else if (L.CPlusPlus)
    return getCXXPersonality(L);
  else if (L.ObjC1)
    return getObjCPersonality(L);
  else
    return getCPersonality(L);
}

static llvm::Constant *getPersonalityFn(CodeGenModule &CGM,
                                        const EHPersonality &Personality) {
  llvm::Constant *Fn =
    CGM.CreateRuntimeFunction(llvm::FunctionType::get(
                                llvm::Type::getInt32Ty(CGM.getLLVMContext()),
                                true),
                              Personality.getPersonalityFnName());
  return Fn;
}

static llvm::Constant *getOpaquePersonalityFn(CodeGenModule &CGM,
                                        const EHPersonality &Personality) {
  llvm::Constant *Fn = getPersonalityFn(CGM, Personality);
  return llvm::ConstantExpr::getBitCast(Fn, CGM.PtrToInt8Ty);
}

/// Check whether a personality function could reasonably be swapped
/// for a C++ personality function.
static bool PersonalityHasOnlyCXXUses(llvm::Constant *Fn) {
  for (llvm::Constant::use_iterator
         I = Fn->use_begin(), E = Fn->use_end(); I != E; ++I) {
    llvm::User *User = *I;

    // Conditionally white-list bitcasts.
    if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(User)) {
      if (CE->getOpcode() != llvm::Instruction::BitCast) return false;
      if (!PersonalityHasOnlyCXXUses(CE))
        return false;
      continue;
    }

    // Otherwise, it has to be a selector call.
    if (!isa<llvm::EHSelectorInst>(User)) return false;

    llvm::EHSelectorInst *Selector = cast<llvm::EHSelectorInst>(User);
    for (unsigned I = 2, E = Selector->getNumArgOperands(); I != E; ++I) {
      // Look for something that would've been returned by the ObjC
      // runtime's GetEHType() method.
      llvm::GlobalVariable *GV
        = dyn_cast<llvm::GlobalVariable>(Selector->getArgOperand(I));
      if (!GV) continue;

      // ObjC EH selector entries are always global variables with
      // names starting like this.
      if (GV->getName().startswith("OBJC_EHTYPE"))
        return false;
    }
  }

  return true;
}

/// Try to use the C++ personality function in ObjC++.  Not doing this
/// can cause some incompatibilities with gcc, which is more
/// aggressive about only using the ObjC++ personality in a function
/// when it really needs it.
void CodeGenModule::SimplifyPersonality() {
  // For now, this is really a Darwin-specific operation.
  if (Context.Target.getTriple().getOS() != llvm::Triple::Darwin)
    return;

  // If we're not in ObjC++ -fexceptions, there's nothing to do.
  if (!Features.CPlusPlus || !Features.ObjC1 || !Features.Exceptions)
    return;

  const EHPersonality &ObjCXX = EHPersonality::get(Features);
  const EHPersonality &CXX = getCXXPersonality(Features);
  if (&ObjCXX == &CXX ||
      ObjCXX.getPersonalityFnName() == CXX.getPersonalityFnName())
    return;

  llvm::Function *Fn =
    getModule().getFunction(ObjCXX.getPersonalityFnName());

  // Nothing to do if it's unused.
  if (!Fn || Fn->use_empty()) return;
  
  // Can't do the optimization if it has non-C++ uses.
  if (!PersonalityHasOnlyCXXUses(Fn)) return;

  // Create the C++ personality function and kill off the old
  // function.
  llvm::Constant *CXXFn = getPersonalityFn(*this, CXX);

  // This can happen if the user is screwing with us.
  if (Fn->getType() != CXXFn->getType()) return;

  Fn->replaceAllUsesWith(CXXFn);
  Fn->eraseFromParent();
}

/// Returns the value to inject into a selector to indicate the
/// presence of a catch-all.
static llvm::Constant *getCatchAllValue(CodeGenFunction &CGF) {
  // Possibly we should use @llvm.eh.catch.all.value here.
  return llvm::ConstantPointerNull::get(CGF.CGM.PtrToInt8Ty);
}

/// Returns the value to inject into a selector to indicate the
/// presence of a cleanup.
static llvm::Constant *getCleanupValue(CodeGenFunction &CGF) {
  return llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
}

namespace {
  /// A cleanup to free the exception object if its initialization
  /// throws.
  struct FreeExceptionCleanup : EHScopeStack::Cleanup {
    FreeExceptionCleanup(llvm::Value *ShouldFreeVar,
                         llvm::Value *ExnLocVar)
      : ShouldFreeVar(ShouldFreeVar), ExnLocVar(ExnLocVar) {}

    llvm::Value *ShouldFreeVar;
    llvm::Value *ExnLocVar;
    
    void Emit(CodeGenFunction &CGF, bool IsForEH) {
      llvm::BasicBlock *FreeBB = CGF.createBasicBlock("free-exnobj");
      llvm::BasicBlock *DoneBB = CGF.createBasicBlock("free-exnobj.done");

      llvm::Value *ShouldFree = CGF.Builder.CreateLoad(ShouldFreeVar,
                                                       "should-free-exnobj");
      CGF.Builder.CreateCondBr(ShouldFree, FreeBB, DoneBB);
      CGF.EmitBlock(FreeBB);
      llvm::Value *ExnLocLocal = CGF.Builder.CreateLoad(ExnLocVar, "exnobj");
      CGF.Builder.CreateCall(getFreeExceptionFn(CGF), ExnLocLocal)
        ->setDoesNotThrow();
      CGF.EmitBlock(DoneBB);
    }
  };
}

// Emits an exception expression into the given location.  This
// differs from EmitAnyExprToMem only in that, if a final copy-ctor
// call is required, an exception within that copy ctor causes
// std::terminate to be invoked.
static void EmitAnyExprToExn(CodeGenFunction &CGF, const Expr *E, 
                             llvm::Value *ExnLoc) {
  // We want to release the allocated exception object if this
  // expression throws.  We do this by pushing an EH-only cleanup
  // block which, furthermore, deactivates itself after the expression
  // is complete.
  llvm::AllocaInst *ShouldFreeVar =
    CGF.CreateTempAlloca(llvm::Type::getInt1Ty(CGF.getLLVMContext()),
                         "should-free-exnobj.var");
  CGF.InitTempAlloca(ShouldFreeVar,
                     llvm::ConstantInt::getFalse(CGF.getLLVMContext()));

  // A variable holding the exception pointer.  This is necessary
  // because the throw expression does not necessarily dominate the
  // cleanup, for example if it appears in a conditional expression.
  llvm::AllocaInst *ExnLocVar =
    CGF.CreateTempAlloca(ExnLoc->getType(), "exnobj.var");

  // Make sure the exception object is cleaned up if there's an
  // exception during initialization.
  // FIXME: stmt expressions might require this to be a normal
  // cleanup, too.
  CGF.EHStack.pushCleanup<FreeExceptionCleanup>(EHCleanup,
                                                ShouldFreeVar,
                                                ExnLocVar);
  EHScopeStack::stable_iterator Cleanup = CGF.EHStack.stable_begin();

  CGF.Builder.CreateStore(ExnLoc, ExnLocVar);
  CGF.Builder.CreateStore(llvm::ConstantInt::getTrue(CGF.getLLVMContext()),
                          ShouldFreeVar);

  // __cxa_allocate_exception returns a void*;  we need to cast this
  // to the appropriate type for the object.
  const llvm::Type *Ty = CGF.ConvertTypeForMem(E->getType())->getPointerTo();
  llvm::Value *TypedExnLoc = CGF.Builder.CreateBitCast(ExnLoc, Ty);

  // FIXME: this isn't quite right!  If there's a final unelided call
  // to a copy constructor, then according to [except.terminate]p1 we
  // must call std::terminate() if that constructor throws, because
  // technically that copy occurs after the exception expression is
  // evaluated but before the exception is caught.  But the best way
  // to handle that is to teach EmitAggExpr to do the final copy
  // differently if it can't be elided.
  CGF.EmitAnyExprToMem(E, TypedExnLoc, /*Volatile*/ false, /*IsInit*/ true);

  CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(CGF.getLLVMContext()),
                          ShouldFreeVar);

  // Technically, the exception object is like a temporary; it has to
  // be cleaned up when its full-expression is complete.
  // Unfortunately, the AST represents full-expressions by creating a
  // ExprWithCleanups, which it only does when there are actually
  // temporaries.
  //
  // If any cleanups have been added since we pushed ours, they must
  // be from temporaries;  this will get popped at the same time.
  // Otherwise we need to pop ours off.  FIXME: this is very brittle.
  if (Cleanup == CGF.EHStack.stable_begin())
    CGF.PopCleanupBlock();
}

llvm::Value *CodeGenFunction::getExceptionSlot() {
  if (!ExceptionSlot) {
    const llvm::Type *i8p = llvm::Type::getInt8PtrTy(getLLVMContext());
    ExceptionSlot = CreateTempAlloca(i8p, "exn.slot");
  }
  return ExceptionSlot;
}

void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) {
  if (!E->getSubExpr()) {
    if (getInvokeDest()) {
      Builder.CreateInvoke(getReThrowFn(*this),
                           getUnreachableBlock(),
                           getInvokeDest())
        ->setDoesNotReturn();
    } else {
      Builder.CreateCall(getReThrowFn(*this))->setDoesNotReturn();
      Builder.CreateUnreachable();
    }

    // throw is an expression, and the expression emitters expect us
    // to leave ourselves at a valid insertion point.
    EmitBlock(createBasicBlock("throw.cont"));

    return;
  }

  QualType ThrowType = E->getSubExpr()->getType();

  // Now allocate the exception object.
  const llvm::Type *SizeTy = ConvertType(getContext().getSizeType());
  uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity();

  llvm::Constant *AllocExceptionFn = getAllocateExceptionFn(*this);
  llvm::CallInst *ExceptionPtr =
    Builder.CreateCall(AllocExceptionFn,
                       llvm::ConstantInt::get(SizeTy, TypeSize),
                       "exception");
  ExceptionPtr->setDoesNotThrow();
  
  EmitAnyExprToExn(*this, E->getSubExpr(), ExceptionPtr);

  // Now throw the exception.
  const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext());
  llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType, 
                                                         /*ForEH=*/true);

  // The address of the destructor.  If the exception type has a
  // trivial destructor (or isn't a record), we just pass null.
  llvm::Constant *Dtor = 0;
  if (const RecordType *RecordTy = ThrowType->getAs<RecordType>()) {
    CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl());
    if (!Record->hasTrivialDestructor()) {
      CXXDestructorDecl *DtorD = Record->getDestructor();
      Dtor = CGM.GetAddrOfCXXDestructor(DtorD, Dtor_Complete);
      Dtor = llvm::ConstantExpr::getBitCast(Dtor, Int8PtrTy);
    }
  }
  if (!Dtor) Dtor = llvm::Constant::getNullValue(Int8PtrTy);

  if (getInvokeDest()) {
    llvm::InvokeInst *ThrowCall =
      Builder.CreateInvoke3(getThrowFn(*this),
                            getUnreachableBlock(), getInvokeDest(),
                            ExceptionPtr, TypeInfo, Dtor);
    ThrowCall->setDoesNotReturn();
  } else {
    llvm::CallInst *ThrowCall =
      Builder.CreateCall3(getThrowFn(*this), ExceptionPtr, TypeInfo, Dtor);
    ThrowCall->setDoesNotReturn();
    Builder.CreateUnreachable();
  }

  // throw is an expression, and the expression emitters expect us
  // to leave ourselves at a valid insertion point.
  EmitBlock(createBasicBlock("throw.cont"));
}

void CodeGenFunction::EmitStartEHSpec(const Decl *D) {
  if (!Exceptions)
    return;
  
  const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D);
  if (FD == 0)
    return;
  const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>();
  if (Proto == 0)
    return;

  assert(!Proto->hasAnyExceptionSpec() && "function with parameter pack");

  if (!Proto->hasExceptionSpec())
    return;

  unsigned NumExceptions = Proto->getNumExceptions();
  EHFilterScope *Filter = EHStack.pushFilter(NumExceptions);

  for (unsigned I = 0; I != NumExceptions; ++I) {
    QualType Ty = Proto->getExceptionType(I);
    QualType ExceptType = Ty.getNonReferenceType().getUnqualifiedType();
    llvm::Value *EHType = CGM.GetAddrOfRTTIDescriptor(ExceptType,
                                                      /*ForEH=*/true);
    Filter->setFilter(I, EHType);
  }
}

void CodeGenFunction::EmitEndEHSpec(const Decl *D) {
  if (!Exceptions)
    return;
  
  const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D);
  if (FD == 0)
    return;
  const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>();
  if (Proto == 0)
    return;

  if (!Proto->hasExceptionSpec())
    return;

  EHStack.popFilter();
}

void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) {
  EnterCXXTryStmt(S);
  EmitStmt(S.getTryBlock());
  ExitCXXTryStmt(S);
}

void CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
  unsigned NumHandlers = S.getNumHandlers();
  EHCatchScope *CatchScope = EHStack.pushCatch(NumHandlers);

  for (unsigned I = 0; I != NumHandlers; ++I) {
    const CXXCatchStmt *C = S.getHandler(I);

    llvm::BasicBlock *Handler = createBasicBlock("catch");
    if (C->getExceptionDecl()) {
      // FIXME: Dropping the reference type on the type into makes it
      // impossible to correctly implement catch-by-reference
      // semantics for pointers.  Unfortunately, this is what all
      // existing compilers do, and it's not clear that the standard
      // personality routine is capable of doing this right.  See C++ DR 388:
      //   http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#388
      QualType CaughtType = C->getCaughtType();
      CaughtType = CaughtType.getNonReferenceType().getUnqualifiedType();

      llvm::Value *TypeInfo = 0;
      if (CaughtType->isObjCObjectPointerType())
        TypeInfo = CGM.getObjCRuntime().GetEHType(CaughtType);
      else
        TypeInfo = CGM.GetAddrOfRTTIDescriptor(CaughtType, /*ForEH=*/true);
      CatchScope->setHandler(I, TypeInfo, Handler);
    } else {
      // No exception decl indicates '...', a catch-all.
      CatchScope->setCatchAllHandler(I, Handler);
    }
  }
}

/// Check whether this is a non-EH scope, i.e. a scope which doesn't
/// affect exception handling.  Currently, the only non-EH scopes are
/// normal-only cleanup scopes.
static bool isNonEHScope(const EHScope &S) {
  switch (S.getKind()) {
  case EHScope::Cleanup:
    return !cast<EHCleanupScope>(S).isEHCleanup();
  case EHScope::Filter:
  case EHScope::Catch:
  case EHScope::Terminate:
    return false;
  }

  // Suppress warning.
  return false;
}

llvm::BasicBlock *CodeGenFunction::getInvokeDestImpl() {
  assert(EHStack.requiresLandingPad());
  assert(!EHStack.empty());

  if (!Exceptions)
    return 0;

  // Check the innermost scope for a cached landing pad.  If this is
  // a non-EH cleanup, we'll check enclosing scopes in EmitLandingPad.
  llvm::BasicBlock *LP = EHStack.begin()->getCachedLandingPad();
  if (LP) return LP;

  // Build the landing pad for this scope.
  LP = EmitLandingPad();
  assert(LP);

  // Cache the landing pad on the innermost scope.  If this is a
  // non-EH scope, cache the landing pad on the enclosing scope, too.
  for (EHScopeStack::iterator ir = EHStack.begin(); true; ++ir) {
    ir->setCachedLandingPad(LP);
    if (!isNonEHScope(*ir)) break;
  }

  return LP;
}

llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
  assert(EHStack.requiresLandingPad());

  // This function contains a hack to work around a design flaw in
  // LLVM's EH IR which breaks semantics after inlining.  This same
  // hack is implemented in llvm-gcc.
  //
  // The LLVM EH abstraction is basically a thin veneer over the
  // traditional GCC zero-cost design: for each range of instructions
  // in the function, there is (at most) one "landing pad" with an
  // associated chain of EH actions.  A language-specific personality
  // function interprets this chain of actions and (1) decides whether
  // or not to resume execution at the landing pad and (2) if so,
  // provides an integer indicating why it's stopping.  In LLVM IR,
  // the association of a landing pad with a range of instructions is
  // achieved via an invoke instruction, the chain of actions becomes
  // the arguments to the @llvm.eh.selector call, and the selector
  // call returns the integer indicator.  Other than the required
  // presence of two intrinsic function calls in the landing pad,
  // the IR exactly describes the layout of the output code.
  //
  // A principal advantage of this design is that it is completely
  // language-agnostic; in theory, the LLVM optimizers can treat
  // landing pads neutrally, and targets need only know how to lower
  // the intrinsics to have a functioning exceptions system (assuming
  // that platform exceptions follow something approximately like the
  // GCC design).  Unfortunately, landing pads cannot be combined in a
  // language-agnostic way: given selectors A and B, there is no way
  // to make a single landing pad which faithfully represents the
  // semantics of propagating an exception first through A, then
  // through B, without knowing how the personality will interpret the
  // (lowered form of the) selectors.  This means that inlining has no
  // choice but to crudely chain invokes (i.e., to ignore invokes in
  // the inlined function, but to turn all unwindable calls into
  // invokes), which is only semantically valid if every unwind stops
  // at every landing pad.
  //
  // Therefore, the invoke-inline hack is to guarantee that every
  // landing pad has a catch-all.
  const bool UseInvokeInlineHack = true;

  for (EHScopeStack::iterator ir = EHStack.begin(); ; ) {
    assert(ir != EHStack.end() &&
           "stack requiring landing pad is nothing but non-EH scopes?");

    // If this is a terminate scope, just use the singleton terminate
    // landing pad.
    if (isa<EHTerminateScope>(*ir))
      return getTerminateLandingPad();

    // If this isn't an EH scope, iterate; otherwise break out.
    if (!isNonEHScope(*ir)) break;
    ++ir;

    // We haven't checked this scope for a cached landing pad yet.
    if (llvm::BasicBlock *LP = ir->getCachedLandingPad())
      return LP;
  }

  // Save the current IR generation state.
  CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();

  const EHPersonality &Personality =
    EHPersonality::get(CGF.CGM.getLangOptions());

  // Create and configure the landing pad.
  llvm::BasicBlock *LP = createBasicBlock("lpad");
  EmitBlock(LP);

  // Save the exception pointer.  It's safe to use a single exception
  // pointer per function because EH cleanups can never have nested
  // try/catches.
  llvm::CallInst *Exn =
    Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_exception), "exn");
  Exn->setDoesNotThrow();
  Builder.CreateStore(Exn, getExceptionSlot());
  
  // Build the selector arguments.
  llvm::SmallVector<llvm::Value*, 8> EHSelector;
  EHSelector.push_back(Exn);
  EHSelector.push_back(getOpaquePersonalityFn(CGM, Personality));

  // Accumulate all the handlers in scope.
  llvm::DenseMap<llvm::Value*, UnwindDest> EHHandlers;
  UnwindDest CatchAll;
  bool HasEHCleanup = false;
  bool HasEHFilter = false;
  llvm::SmallVector<llvm::Value*, 8> EHFilters;
  for (EHScopeStack::iterator I = EHStack.begin(), E = EHStack.end();
         I != E; ++I) {

    switch (I->getKind()) {
    case EHScope::Cleanup:
      if (!HasEHCleanup)
        HasEHCleanup = cast<EHCleanupScope>(*I).isEHCleanup();
      // We otherwise don't care about cleanups.
      continue;

    case EHScope::Filter: {
      assert(I.next() == EHStack.end() && "EH filter is not end of EH stack");
      assert(!CatchAll.isValid() && "EH filter reached after catch-all");

      // Filter scopes get added to the selector in wierd ways.
      EHFilterScope &Filter = cast<EHFilterScope>(*I);
      HasEHFilter = true;

      // Add all the filter values which we aren't already explicitly
      // catching.
      for (unsigned I = 0, E = Filter.getNumFilters(); I != E; ++I) {
        llvm::Value *FV = Filter.getFilter(I);
        if (!EHHandlers.count(FV))
          EHFilters.push_back(FV);
      }
      goto done;
    }

    case EHScope::Terminate:
      // Terminate scopes are basically catch-alls.
      assert(!CatchAll.isValid());
      CatchAll = UnwindDest(getTerminateHandler(),
                            EHStack.getEnclosingEHCleanup(I),
                            cast<EHTerminateScope>(*I).getDestIndex());
      goto done;

    case EHScope::Catch:
      break;
    }

    EHCatchScope &Catch = cast<EHCatchScope>(*I);
    for (unsigned HI = 0, HE = Catch.getNumHandlers(); HI != HE; ++HI) {
      EHCatchScope::Handler Handler = Catch.getHandler(HI);

      // Catch-all.  We should only have one of these per catch.
      if (!Handler.Type) {
        assert(!CatchAll.isValid());
        CatchAll = UnwindDest(Handler.Block,
                              EHStack.getEnclosingEHCleanup(I),
                              Handler.Index);
        continue;
      }

      // Check whether we already have a handler for this type.
      UnwindDest &Dest = EHHandlers[Handler.Type];
      if (Dest.isValid()) continue;

      EHSelector.push_back(Handler.Type);
      Dest = UnwindDest(Handler.Block,
                        EHStack.getEnclosingEHCleanup(I),
                        Handler.Index);
    }

    // Stop if we found a catch-all.
    if (CatchAll.isValid()) break;
  }

 done:
  unsigned LastToEmitInLoop = EHSelector.size();

  // If we have a catch-all, add null to the selector.
  if (CatchAll.isValid()) {
    EHSelector.push_back(getCatchAllValue(CGF));

  // If we have an EH filter, we need to add those handlers in the
  // right place in the selector, which is to say, at the end.
  } else if (HasEHFilter) {
    // Create a filter expression: an integer constant saying how many
    // filters there are (+1 to avoid ambiguity with 0 for cleanup),
    // followed by the filter types.  The personality routine only
    // lands here if the filter doesn't match.
    EHSelector.push_back(llvm::ConstantInt::get(Builder.getInt32Ty(),
                                                EHFilters.size() + 1));
    EHSelector.append(EHFilters.begin(), EHFilters.end());

    // Also check whether we need a cleanup.
    if (UseInvokeInlineHack || HasEHCleanup)
      EHSelector.push_back(UseInvokeInlineHack
                           ? getCatchAllValue(CGF)
                           : getCleanupValue(CGF));

  // Otherwise, signal that we at least have cleanups.
  } else if (UseInvokeInlineHack || HasEHCleanup) {
    EHSelector.push_back(UseInvokeInlineHack
                         ? getCatchAllValue(CGF)
                         : getCleanupValue(CGF));
  } else {
    assert(LastToEmitInLoop > 2);
    LastToEmitInLoop--;
  }

  assert(EHSelector.size() >= 3 && "selector call has only two arguments!");

  // Tell the backend how to generate the landing pad.
  llvm::CallInst *Selection =
    Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_selector),
                       EHSelector.begin(), EHSelector.end(), "eh.selector");
  Selection->setDoesNotThrow();
  
  // Select the right handler.
  llvm::Value *llvm_eh_typeid_for =
    CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for);

  // The results of llvm_eh_typeid_for aren't reliable --- at least
  // not locally --- so we basically have to do this as an 'if' chain.
  // We walk through the first N-1 catch clauses, testing and chaining,
  // and then fall into the final clause (which is either a cleanup, a
  // filter (possibly with a cleanup), a catch-all, or another catch).
  for (unsigned I = 2; I != LastToEmitInLoop; ++I) {
    llvm::Value *Type = EHSelector[I];
    UnwindDest Dest = EHHandlers[Type];
    assert(Dest.isValid() && "no handler entry for value in selector?");

    // Figure out where to branch on a match.  As a debug code-size
    // optimization, if the scope depth matches the innermost cleanup,
    // we branch directly to the catch handler.
    llvm::BasicBlock *Match = Dest.getBlock();
    bool MatchNeedsCleanup =
      Dest.getScopeDepth() != EHStack.getInnermostEHCleanup();
    if (MatchNeedsCleanup)
      Match = createBasicBlock("eh.match");

    llvm::BasicBlock *Next = createBasicBlock("eh.next");

    // Check whether the exception matches.
    llvm::CallInst *Id
      = Builder.CreateCall(llvm_eh_typeid_for,
                           Builder.CreateBitCast(Type, CGM.PtrToInt8Ty));
    Id->setDoesNotThrow();
    Builder.CreateCondBr(Builder.CreateICmpEQ(Selection, Id),
                         Match, Next);
    
    // Emit match code if necessary.
    if (MatchNeedsCleanup) {
      EmitBlock(Match);
      EmitBranchThroughEHCleanup(Dest);
    }

    // Continue to the next match.
    EmitBlock(Next);
  }

  // Emit the final case in the selector.
  // This might be a catch-all....
  if (CatchAll.isValid()) {
    assert(isa<llvm::ConstantPointerNull>(EHSelector.back()));
    EmitBranchThroughEHCleanup(CatchAll);

  // ...or an EH filter...
  } else if (HasEHFilter) {
    llvm::Value *SavedSelection = Selection;

    // First, unwind out to the outermost scope if necessary.
    if (EHStack.hasEHCleanups()) {
      // The end here might not dominate the beginning, so we might need to
      // save the selector if we need it.
      llvm::AllocaInst *SelectorVar = 0;
      if (HasEHCleanup) {
        SelectorVar = CreateTempAlloca(Builder.getInt32Ty(), "selector.var");
        Builder.CreateStore(Selection, SelectorVar);
      }

      llvm::BasicBlock *CleanupContBB = createBasicBlock("ehspec.cleanup.cont");
      EmitBranchThroughEHCleanup(UnwindDest(CleanupContBB, EHStack.stable_end(),
                                            EHStack.getNextEHDestIndex()));
      EmitBlock(CleanupContBB);

      if (HasEHCleanup)
        SavedSelection = Builder.CreateLoad(SelectorVar, "ehspec.saved-selector");
    }

    // If there was a cleanup, we'll need to actually check whether we
    // landed here because the filter triggered.
    if (UseInvokeInlineHack || HasEHCleanup) {
      llvm::BasicBlock *RethrowBB = createBasicBlock("cleanup");
      llvm::BasicBlock *UnexpectedBB = createBasicBlock("ehspec.unexpected");

      llvm::Constant *Zero = llvm::ConstantInt::get(Builder.getInt32Ty(), 0);
      llvm::Value *FailsFilter =
        Builder.CreateICmpSLT(SavedSelection, Zero, "ehspec.fails");
      Builder.CreateCondBr(FailsFilter, UnexpectedBB, RethrowBB);

      // The rethrow block is where we land if this was a cleanup.
      // TODO: can this be _Unwind_Resume if the InvokeInlineHack is off?
      EmitBlock(RethrowBB);
      Builder.CreateCall(getUnwindResumeOrRethrowFn(),
                         Builder.CreateLoad(getExceptionSlot()))
        ->setDoesNotReturn();
      Builder.CreateUnreachable();

      EmitBlock(UnexpectedBB);
    }

    // Call __cxa_call_unexpected.  This doesn't need to be an invoke
    // because __cxa_call_unexpected magically filters exceptions
    // according to the last landing pad the exception was thrown
    // into.  Seriously.
    Builder.CreateCall(getUnexpectedFn(*this),
                       Builder.CreateLoad(getExceptionSlot()))
      ->setDoesNotReturn();
    Builder.CreateUnreachable();

  // ...or a normal catch handler...
  } else if (!UseInvokeInlineHack && !HasEHCleanup) {
    llvm::Value *Type = EHSelector.back();
    EmitBranchThroughEHCleanup(EHHandlers[Type]);

  // ...or a cleanup.
  } else {
    EmitBranchThroughEHCleanup(getRethrowDest());
  }

  // Restore the old IR generation state.
  Builder.restoreIP(SavedIP);

  return LP;
}

namespace {
  /// A cleanup to call __cxa_end_catch.  In many cases, the caught
  /// exception type lets us state definitively that the thrown exception
  /// type does not have a destructor.  In particular:
  ///   - Catch-alls tell us nothing, so we have to conservatively
  ///     assume that the thrown exception might have a destructor.
  ///   - Catches by reference behave according to their base types.
  ///   - Catches of non-record types will only trigger for exceptions
  ///     of non-record types, which never have destructors.
  ///   - Catches of record types can trigger for arbitrary subclasses
  ///     of the caught type, so we have to assume the actual thrown
  ///     exception type might have a throwing destructor, even if the
  ///     caught type's destructor is trivial or nothrow.
  struct CallEndCatch : EHScopeStack::Cleanup {
    CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {}
    bool MightThrow;

    void Emit(CodeGenFunction &CGF, bool IsForEH) {
      if (!MightThrow) {
        CGF.Builder.CreateCall(getEndCatchFn(CGF))->setDoesNotThrow();
        return;
      }

      CGF.EmitCallOrInvoke(getEndCatchFn(CGF), 0, 0);
    }
  };
}

/// Emits a call to __cxa_begin_catch and enters a cleanup to call
/// __cxa_end_catch.
///
/// \param EndMightThrow - true if __cxa_end_catch might throw
static llvm::Value *CallBeginCatch(CodeGenFunction &CGF,
                                   llvm::Value *Exn,
                                   bool EndMightThrow) {
  llvm::CallInst *Call = CGF.Builder.CreateCall(getBeginCatchFn(CGF), Exn);
  Call->setDoesNotThrow();

  CGF.EHStack.pushCleanup<CallEndCatch>(NormalAndEHCleanup, EndMightThrow);

  return Call;
}

/// A "special initializer" callback for initializing a catch
/// parameter during catch initialization.
static void InitCatchParam(CodeGenFunction &CGF,
                           const VarDecl &CatchParam,
                           llvm::Value *ParamAddr) {
  // Load the exception from where the landing pad saved it.
  llvm::Value *Exn = CGF.Builder.CreateLoad(CGF.getExceptionSlot(), "exn");

  CanQualType CatchType =
    CGF.CGM.getContext().getCanonicalType(CatchParam.getType());
  const llvm::Type *LLVMCatchTy = CGF.ConvertTypeForMem(CatchType);

  // If we're catching by reference, we can just cast the object
  // pointer to the appropriate pointer.
  if (isa<ReferenceType>(CatchType)) {
    QualType CaughtType = cast<ReferenceType>(CatchType)->getPointeeType();
    bool EndCatchMightThrow = CaughtType->isRecordType();

    // __cxa_begin_catch returns the adjusted object pointer.
    llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, EndCatchMightThrow);

    // We have no way to tell the personality function that we're
    // catching by reference, so if we're catching a pointer,
    // __cxa_begin_catch will actually return that pointer by value.
    if (const PointerType *PT = dyn_cast<PointerType>(CaughtType)) {
      QualType PointeeType = PT->getPointeeType();

      // When catching by reference, generally we should just ignore
      // this by-value pointer and use the exception object instead.
      if (!PointeeType->isRecordType()) {

        // Exn points to the struct _Unwind_Exception header, which
        // we have to skip past in order to reach the exception data.
        unsigned HeaderSize =
          CGF.CGM.getTargetCodeGenInfo().getSizeOfUnwindException();
        AdjustedExn = CGF.Builder.CreateConstGEP1_32(Exn, HeaderSize);

      // However, if we're catching a pointer-to-record type that won't
      // work, because the personality function might have adjusted
      // the pointer.  There's actually no way for us to fully satisfy
      // the language/ABI contract here:  we can't use Exn because it
      // might have the wrong adjustment, but we can't use the by-value
      // pointer because it's off by a level of abstraction.
      //
      // The current solution is to dump the adjusted pointer into an
      // alloca, which breaks language semantics (because changing the
      // pointer doesn't change the exception) but at least works.
      // The better solution would be to filter out non-exact matches
      // and rethrow them, but this is tricky because the rethrow
      // really needs to be catchable by other sites at this landing
      // pad.  The best solution is to fix the personality function.
      } else {
        // Pull the pointer for the reference type off.
        const llvm::Type *PtrTy =
          cast<llvm::PointerType>(LLVMCatchTy)->getElementType();

        // Create the temporary and write the adjusted pointer into it.
        llvm::Value *ExnPtrTmp = CGF.CreateTempAlloca(PtrTy, "exn.byref.tmp");
        llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
        CGF.Builder.CreateStore(Casted, ExnPtrTmp);

        // Bind the reference to the temporary.
        AdjustedExn = ExnPtrTmp;
      }
    }

    llvm::Value *ExnCast =
      CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref");
    CGF.Builder.CreateStore(ExnCast, ParamAddr);
    return;
  }

  // Non-aggregates (plus complexes).
  bool IsComplex = false;
  if (!CGF.hasAggregateLLVMType(CatchType) ||
      (IsComplex = CatchType->isAnyComplexType())) {
    llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, false);
    
    // If the catch type is a pointer type, __cxa_begin_catch returns
    // the pointer by value.
    if (CatchType->hasPointerRepresentation()) {
      llvm::Value *CastExn =
        CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted");
      CGF.Builder.CreateStore(CastExn, ParamAddr);
      return;
    }

    // Otherwise, it returns a pointer into the exception object.

    const llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok
    llvm::Value *Cast = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);

    if (IsComplex) {
      CGF.StoreComplexToAddr(CGF.LoadComplexFromAddr(Cast, /*volatile*/ false),
                             ParamAddr, /*volatile*/ false);
    } else {
      unsigned Alignment =
        CGF.getContext().getDeclAlign(&CatchParam).getQuantity();
      llvm::Value *ExnLoad = CGF.Builder.CreateLoad(Cast, "exn.scalar");
      CGF.EmitStoreOfScalar(ExnLoad, ParamAddr, /*volatile*/ false, Alignment,
                            CatchType);
    }
    return;
  }

  // FIXME: this *really* needs to be done via a proper, Sema-emitted
  // initializer expression.

  CXXRecordDecl *RD = CatchType.getTypePtr()->getAsCXXRecordDecl();
  assert(RD && "aggregate catch type was not a record!");

  const llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok

  if (RD->hasTrivialCopyConstructor()) {
    llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, true);
    llvm::Value *Cast = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
    CGF.EmitAggregateCopy(ParamAddr, Cast, CatchType);
    return;
  }

  // We have to call __cxa_get_exception_ptr to get the adjusted
  // pointer before copying.
  llvm::CallInst *AdjustedExn =
    CGF.Builder.CreateCall(getGetExceptionPtrFn(CGF), Exn);
  AdjustedExn->setDoesNotThrow();
  llvm::Value *Cast = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);

  CXXConstructorDecl *CD = RD->getCopyConstructor(CGF.getContext(), 0);
  assert(CD && "record has no copy constructor!");
  llvm::Value *CopyCtor = CGF.CGM.GetAddrOfCXXConstructor(CD, Ctor_Complete);

  CallArgList CallArgs;
  CallArgs.push_back(std::make_pair(RValue::get(ParamAddr),
                                    CD->getThisType(CGF.getContext())));
  CallArgs.push_back(std::make_pair(RValue::get(Cast),
                                    CD->getParamDecl(0)->getType()));

  const FunctionProtoType *FPT
    = CD->getType()->getAs<FunctionProtoType>();

  // Call the copy ctor in a terminate scope.
  CGF.EHStack.pushTerminate();
  CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(CallArgs, FPT),
               CopyCtor, ReturnValueSlot(), CallArgs, CD);
  CGF.EHStack.popTerminate();

  // Finally we can call __cxa_begin_catch.
  CallBeginCatch(CGF, Exn, true);
}

/// Begins a catch statement by initializing the catch variable and
/// calling __cxa_begin_catch.
static void BeginCatch(CodeGenFunction &CGF,
                       const CXXCatchStmt *S) {
  // We have to be very careful with the ordering of cleanups here:
  //   C++ [except.throw]p4:
  //     The destruction [of the exception temporary] occurs
  //     immediately after the destruction of the object declared in
  //     the exception-declaration in the handler.
  //
  // So the precise ordering is:
  //   1.  Construct catch variable.
  //   2.  __cxa_begin_catch
  //   3.  Enter __cxa_end_catch cleanup
  //   4.  Enter dtor cleanup
  //
  // We do this by initializing the exception variable with a
  // "special initializer", InitCatchParam.  Delegation sequence:
  //   - ExitCXXTryStmt opens a RunCleanupsScope
  //     - EmitLocalBlockVarDecl creates the variable and debug info
  //       - InitCatchParam initializes the variable from the exception
  //         - CallBeginCatch calls __cxa_begin_catch
  //         - CallBeginCatch enters the __cxa_end_catch cleanup
  //     - EmitLocalBlockVarDecl enters the variable destructor cleanup
  //   - EmitCXXTryStmt emits the code for the catch body
  //   - EmitCXXTryStmt close the RunCleanupsScope

  VarDecl *CatchParam = S->getExceptionDecl();
  if (!CatchParam) {
    llvm::Value *Exn = CGF.Builder.CreateLoad(CGF.getExceptionSlot(), "exn");
    CallBeginCatch(CGF, Exn, true);
    return;
  }

  // Emit the local.
  CGF.EmitAutoVarDecl(*CatchParam, &InitCatchParam);
}

namespace {
  struct CallRethrow : EHScopeStack::Cleanup {
    void Emit(CodeGenFunction &CGF, bool IsForEH) {
      CGF.EmitCallOrInvoke(getReThrowFn(CGF), 0, 0);
    }
  };
}

void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
  unsigned NumHandlers = S.getNumHandlers();
  EHCatchScope &CatchScope = cast<EHCatchScope>(*EHStack.begin());
  assert(CatchScope.getNumHandlers() == NumHandlers);

  // Copy the handler blocks off before we pop the EH stack.  Emitting
  // the handlers might scribble on this memory.
  llvm::SmallVector<EHCatchScope::Handler, 8> Handlers(NumHandlers);
  memcpy(Handlers.data(), CatchScope.begin(),
         NumHandlers * sizeof(EHCatchScope::Handler));
  EHStack.popCatch();

  // The fall-through block.
  llvm::BasicBlock *ContBB = createBasicBlock("try.cont");

  // We just emitted the body of the try; jump to the continue block.
  if (HaveInsertPoint())
    Builder.CreateBr(ContBB);

  // Determine if we need an implicit rethrow for all these catch handlers.
  bool ImplicitRethrow = false;
  if (IsFnTryBlock)
    ImplicitRethrow = isa<CXXDestructorDecl>(CurCodeDecl) ||
                      isa<CXXConstructorDecl>(CurCodeDecl);

  for (unsigned I = 0; I != NumHandlers; ++I) {
    llvm::BasicBlock *CatchBlock = Handlers[I].Block;
    EmitBlock(CatchBlock);

    // Catch the exception if this isn't a catch-all.
    const CXXCatchStmt *C = S.getHandler(I);

    // Enter a cleanup scope, including the catch variable and the
    // end-catch.
    RunCleanupsScope CatchScope(*this);

    // Initialize the catch variable and set up the cleanups.
    BeginCatch(*this, C);

    // If there's an implicit rethrow, push a normal "cleanup" to call
    // _cxa_rethrow.  This needs to happen before __cxa_end_catch is
    // called, and so it is pushed after BeginCatch.
    if (ImplicitRethrow)
      EHStack.pushCleanup<CallRethrow>(NormalCleanup);

    // Perform the body of the catch.
    EmitStmt(C->getHandlerBlock());

    // Fall out through the catch cleanups.
    CatchScope.ForceCleanup();

    // Branch out of the try.
    if (HaveInsertPoint())
      Builder.CreateBr(ContBB);
  }

  EmitBlock(ContBB);
}

namespace {
  struct CallEndCatchForFinally : EHScopeStack::Cleanup {
    llvm::Value *ForEHVar;
    llvm::Value *EndCatchFn;
    CallEndCatchForFinally(llvm::Value *ForEHVar, llvm::Value *EndCatchFn)
      : ForEHVar(ForEHVar), EndCatchFn(EndCatchFn) {}

    void Emit(CodeGenFunction &CGF, bool IsForEH) {
      llvm::BasicBlock *EndCatchBB = CGF.createBasicBlock("finally.endcatch");
      llvm::BasicBlock *CleanupContBB =
        CGF.createBasicBlock("finally.cleanup.cont");

      llvm::Value *ShouldEndCatch =
        CGF.Builder.CreateLoad(ForEHVar, "finally.endcatch");
      CGF.Builder.CreateCondBr(ShouldEndCatch, EndCatchBB, CleanupContBB);
      CGF.EmitBlock(EndCatchBB);
      CGF.EmitCallOrInvoke(EndCatchFn, 0, 0); // catch-all, so might throw
      CGF.EmitBlock(CleanupContBB);
    }
  };

  struct PerformFinally : EHScopeStack::Cleanup {
    const Stmt *Body;
    llvm::Value *ForEHVar;
    llvm::Value *EndCatchFn;
    llvm::Value *RethrowFn;
    llvm::Value *SavedExnVar;

    PerformFinally(const Stmt *Body, llvm::Value *ForEHVar,
                   llvm::Value *EndCatchFn,
                   llvm::Value *RethrowFn, llvm::Value *SavedExnVar)
      : Body(Body), ForEHVar(ForEHVar), EndCatchFn(EndCatchFn),
        RethrowFn(RethrowFn), SavedExnVar(SavedExnVar) {}

    void Emit(CodeGenFunction &CGF, bool IsForEH) {
      // Enter a cleanup to call the end-catch function if one was provided.
      if (EndCatchFn)
        CGF.EHStack.pushCleanup<CallEndCatchForFinally>(NormalAndEHCleanup,
                                                        ForEHVar, EndCatchFn);

      // Save the current cleanup destination in case there are
      // cleanups in the finally block.
      llvm::Value *SavedCleanupDest =
        CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot(),
                               "cleanup.dest.saved");

      // Emit the finally block.
      CGF.EmitStmt(Body);

      // If the end of the finally is reachable, check whether this was
      // for EH.  If so, rethrow.
      if (CGF.HaveInsertPoint()) {
        llvm::BasicBlock *RethrowBB = CGF.createBasicBlock("finally.rethrow");
        llvm::BasicBlock *ContBB = CGF.createBasicBlock("finally.cont");

        llvm::Value *ShouldRethrow =
          CGF.Builder.CreateLoad(ForEHVar, "finally.shouldthrow");
        CGF.Builder.CreateCondBr(ShouldRethrow, RethrowBB, ContBB);

        CGF.EmitBlock(RethrowBB);
        if (SavedExnVar) {
          llvm::Value *Args[] = { CGF.Builder.CreateLoad(SavedExnVar) };
          CGF.EmitCallOrInvoke(RethrowFn, Args, Args+1);
        } else {
          CGF.EmitCallOrInvoke(RethrowFn, 0, 0);
        }
        CGF.Builder.CreateUnreachable();

        CGF.EmitBlock(ContBB);

        // Restore the cleanup destination.
        CGF.Builder.CreateStore(SavedCleanupDest,
                                CGF.getNormalCleanupDestSlot());
      }

      // Leave the end-catch cleanup.  As an optimization, pretend that
      // the fallthrough path was inaccessible; we've dynamically proven
      // that we're not in the EH case along that path.
      if (EndCatchFn) {
        CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
        CGF.PopCleanupBlock();
        CGF.Builder.restoreIP(SavedIP);
      }
    
      // Now make sure we actually have an insertion point or the
      // cleanup gods will hate us.
      CGF.EnsureInsertPoint();
    }
  };
}

/// Enters a finally block for an implementation using zero-cost
/// exceptions.  This is mostly general, but hard-codes some
/// language/ABI-specific behavior in the catch-all sections.
CodeGenFunction::FinallyInfo
CodeGenFunction::EnterFinallyBlock(const Stmt *Body,
                                   llvm::Constant *BeginCatchFn,
                                   llvm::Constant *EndCatchFn,
                                   llvm::Constant *RethrowFn) {
  assert((BeginCatchFn != 0) == (EndCatchFn != 0) &&
         "begin/end catch functions not paired");
  assert(RethrowFn && "rethrow function is required");

  // The rethrow function has one of the following two types:
  //   void (*)()
  //   void (*)(void*)
  // In the latter case we need to pass it the exception object.
  // But we can't use the exception slot because the @finally might
  // have a landing pad (which would overwrite the exception slot).
  const llvm::FunctionType *RethrowFnTy =
    cast<llvm::FunctionType>(
      cast<llvm::PointerType>(RethrowFn->getType())
      ->getElementType());
  llvm::Value *SavedExnVar = 0;
  if (RethrowFnTy->getNumParams())
    SavedExnVar = CreateTempAlloca(Builder.getInt8PtrTy(), "finally.exn");

  // A finally block is a statement which must be executed on any edge
  // out of a given scope.  Unlike a cleanup, the finally block may
  // contain arbitrary control flow leading out of itself.  In
  // addition, finally blocks should always be executed, even if there
  // are no catch handlers higher on the stack.  Therefore, we
  // surround the protected scope with a combination of a normal
  // cleanup (to catch attempts to break out of the block via normal
  // control flow) and an EH catch-all (semantically "outside" any try
  // statement to which the finally block might have been attached).
  // The finally block itself is generated in the context of a cleanup
  // which conditionally leaves the catch-all.

  FinallyInfo Info;

  // Jump destination for performing the finally block on an exception
  // edge.  We'll never actually reach this block, so unreachable is
  // fine.
  JumpDest RethrowDest = getJumpDestInCurrentScope(getUnreachableBlock());

  // Whether the finally block is being executed for EH purposes.
  llvm::AllocaInst *ForEHVar = CreateTempAlloca(CGF.Builder.getInt1Ty(),
                                                "finally.for-eh");
  InitTempAlloca(ForEHVar, llvm::ConstantInt::getFalse(getLLVMContext()));

  // Enter a normal cleanup which will perform the @finally block.
  EHStack.pushCleanup<PerformFinally>(NormalCleanup, Body,
                                      ForEHVar, EndCatchFn,
                                      RethrowFn, SavedExnVar);

  // Enter a catch-all scope.
  llvm::BasicBlock *CatchAllBB = createBasicBlock("finally.catchall");
  CGBuilderTy::InsertPoint SavedIP = Builder.saveIP();
  Builder.SetInsertPoint(CatchAllBB);

  // If there's a begin-catch function, call it.
  if (BeginCatchFn) {
    Builder.CreateCall(BeginCatchFn, Builder.CreateLoad(getExceptionSlot()))
      ->setDoesNotThrow();
  }

  // If we need to remember the exception pointer to rethrow later, do so.
  if (SavedExnVar) {
    llvm::Value *SavedExn = Builder.CreateLoad(getExceptionSlot());
    Builder.CreateStore(SavedExn, SavedExnVar);
  }

  // Tell the finally block that we're in EH.
  Builder.CreateStore(llvm::ConstantInt::getTrue(getLLVMContext()), ForEHVar);

  // Thread a jump through the finally cleanup.
  EmitBranchThroughCleanup(RethrowDest);

  Builder.restoreIP(SavedIP);

  EHCatchScope *CatchScope = EHStack.pushCatch(1);
  CatchScope->setCatchAllHandler(0, CatchAllBB);

  return Info;
}

void CodeGenFunction::ExitFinallyBlock(FinallyInfo &Info) {
  // Leave the finally catch-all.
  EHCatchScope &Catch = cast<EHCatchScope>(*EHStack.begin());
  llvm::BasicBlock *CatchAllBB = Catch.getHandler(0).Block;
  EHStack.popCatch();

  // And leave the normal cleanup.
  PopCleanupBlock();

  CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
  EmitBlock(CatchAllBB, true);

  Builder.restoreIP(SavedIP);
}

llvm::BasicBlock *CodeGenFunction::getTerminateLandingPad() {
  if (TerminateLandingPad)
    return TerminateLandingPad;

  CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();

  // This will get inserted at the end of the function.
  TerminateLandingPad = createBasicBlock("terminate.lpad");
  Builder.SetInsertPoint(TerminateLandingPad);

  // Tell the backend that this is a landing pad.
  llvm::CallInst *Exn =
    Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_exception), "exn");
  Exn->setDoesNotThrow();

  const EHPersonality &Personality = EHPersonality::get(CGM.getLangOptions());
  
  // Tell the backend what the exception table should be:
  // nothing but a catch-all.
  llvm::Value *Args[3] = { Exn, getOpaquePersonalityFn(CGM, Personality),
                           getCatchAllValue(*this) };
  Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_selector),
                     Args, Args+3, "eh.selector")
    ->setDoesNotThrow();

  llvm::CallInst *TerminateCall = Builder.CreateCall(getTerminateFn(*this));
  TerminateCall->setDoesNotReturn();
  TerminateCall->setDoesNotThrow();
  CGF.Builder.CreateUnreachable();

  // Restore the saved insertion state.
  Builder.restoreIP(SavedIP);

  return TerminateLandingPad;
}

llvm::BasicBlock *CodeGenFunction::getTerminateHandler() {
  if (TerminateHandler)
    return TerminateHandler;

  CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();

  // Set up the terminate handler.  This block is inserted at the very
  // end of the function by FinishFunction.
  TerminateHandler = createBasicBlock("terminate.handler");
  Builder.SetInsertPoint(TerminateHandler);
  llvm::CallInst *TerminateCall = Builder.CreateCall(getTerminateFn(*this));
  TerminateCall->setDoesNotReturn();
  TerminateCall->setDoesNotThrow();
  Builder.CreateUnreachable();

  // Restore the saved insertion state.
  Builder.restoreIP(SavedIP);

  return TerminateHandler;
}

CodeGenFunction::UnwindDest CodeGenFunction::getRethrowDest() {
  if (RethrowBlock.isValid()) return RethrowBlock;

  CGBuilderTy::InsertPoint SavedIP = Builder.saveIP();

  // We emit a jump to a notional label at the outermost unwind state.
  llvm::BasicBlock *Unwind = createBasicBlock("eh.resume");
  Builder.SetInsertPoint(Unwind);

  const EHPersonality &Personality = EHPersonality::get(CGM.getLangOptions());

  // This can always be a call because we necessarily didn't find
  // anything on the EH stack which needs our help.
  llvm::StringRef RethrowName = Personality.getCatchallRethrowFnName();
  llvm::Constant *RethrowFn;
  if (!RethrowName.empty())
    RethrowFn = getCatchallRethrowFn(*this, RethrowName);
  else
    RethrowFn = getUnwindResumeOrRethrowFn();

  Builder.CreateCall(RethrowFn, Builder.CreateLoad(getExceptionSlot()))
    ->setDoesNotReturn();
  Builder.CreateUnreachable();

  Builder.restoreIP(SavedIP);

  RethrowBlock = UnwindDest(Unwind, EHStack.stable_end(), 0);
  return RethrowBlock;
}

EHScopeStack::Cleanup::~Cleanup() {
  llvm_unreachable("Cleanup is indestructable");
}
