示例#1
0
static bool IsDeletingDtor(GlobalDecl GD) {
  const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl());
  if (isa<CXXDestructorDecl>(MD)) {
    return GD.getDtorType() == Dtor_Deleting;
  }
  return false;
}
示例#2
0
void CodeGenVTables::EmitThunks(GlobalDecl GD) {
  const CXXMethodDecl *MD =
    cast<CXXMethodDecl>(GD.getDecl())->getCanonicalDecl();

  // We don't need to generate thunks for the base destructor.
  if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
    return;

  const VTableContextBase::ThunkInfoVectorTy *ThunkInfoVector =
      VTContext->getThunkInfo(GD);

  if (!ThunkInfoVector)
    return;

  for (const ThunkInfo& Thunk : *ThunkInfoVector)
    maybeEmitThunk(GD, Thunk, /*ForVTable=*/false);
}
示例#3
0
bool CodeGenVTables::needsVTTParameter(GlobalDecl GD) {
  const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
  
  // We don't have any virtual bases, just return early.
  if (!MD->getParent()->getNumVBases())
    return false;
  
  // Check if we have a base constructor.
  if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
    return true;

  // Check if we have a base destructor.
  if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
    return true;
  
  return false;
}
示例#4
0
void CodeGenVTables::EmitThunks(GlobalDecl GD)
{
  const CXXMethodDecl *MD = 
    cast<CXXMethodDecl>(GD.getDecl())->getCanonicalDecl();

  // We don't need to generate thunks for the base destructor.
  if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
    return;

  const VTableContext::ThunkInfoVectorTy *ThunkInfoVector =
    VTContext.getThunkInfo(MD);
  if (!ThunkInfoVector)
    return;

  for (unsigned I = 0, E = ThunkInfoVector->size(); I != E; ++I)
    EmitThunk(GD, (*ThunkInfoVector)[I],
              /*UseAvailableExternallyLinkage=*/false);
}
示例#5
0
void CodeGenVTables::EmitThunks(GlobalDecl GD)
{
  const CXXMethodDecl *MD = 
    cast<CXXMethodDecl>(GD.getDecl())->getCanonicalDecl();

  // We don't need to generate thunks for the base destructor.
  if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
    return;

  const VTableContextBase::ThunkInfoVectorTy *ThunkInfoVector;
  if (MicrosoftVTContext.isValid()) {
    ThunkInfoVector = MicrosoftVTContext->getThunkInfo(GD);
  } else {
    ThunkInfoVector = ItaniumVTContext.getThunkInfo(GD);
  }

  if (!ThunkInfoVector)
    return;

  for (unsigned I = 0, E = ThunkInfoVector->size(); I != E; ++I)
    emitThunk(GD, (*ThunkInfoVector)[I], /*ForVTable=*/false);
}
示例#6
0
文件: CGException.cpp 项目: aaasz/SHP
void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) {
  // Pointer to the personality function
  llvm::Constant *Personality =
    CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty
                                                      (VMContext),
                                                      true),
                              "__gxx_personality_v0");
  Personality = llvm::ConstantExpr::getBitCast(Personality, PtrToInt8Ty);
  llvm::Value *llvm_eh_exception =
    CGM.getIntrinsic(llvm::Intrinsic::eh_exception);
  llvm::Value *llvm_eh_selector =
    CGM.getIntrinsic(llvm::Intrinsic::eh_selector);

  llvm::BasicBlock *PrevLandingPad = getInvokeDest();
  llvm::BasicBlock *TryHandler = createBasicBlock("try.handler");
  llvm::BasicBlock *FinallyBlock = createBasicBlock("finally");
  llvm::BasicBlock *FinallyRethrow = createBasicBlock("finally.throw");
  llvm::BasicBlock *FinallyEnd = createBasicBlock("finally.end");

  // Push an EH context entry, used for handling rethrows.
  PushCleanupBlock(FinallyBlock);

  // Emit the statements in the try {} block
  setInvokeDest(TryHandler);

  // FIXME: We should not have to do this here.  The AST should have the member
  // initializers under the CXXTryStmt's TryBlock.
  if (OuterTryBlock == &S) {
    GlobalDecl GD = CurGD;
    const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());

    if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
      size_t OldCleanupStackSize = CleanupEntries.size();
      EmitCtorPrologue(CD, CurGD.getCtorType());
      EmitStmt(S.getTryBlock());

      // If any of the member initializers are temporaries bound to references
      // make sure to emit their destructors.
      EmitCleanupBlocks(OldCleanupStackSize);
    } else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) {
      llvm::BasicBlock *DtorEpilogue  = createBasicBlock("dtor.epilogue");
      PushCleanupBlock(DtorEpilogue);

      EmitStmt(S.getTryBlock());

      CleanupBlockInfo Info = PopCleanupBlock();

      assert(Info.CleanupBlock == DtorEpilogue && "Block mismatch!");
      EmitBlock(DtorEpilogue);
      EmitDtorEpilogue(DD, GD.getDtorType());

      if (Info.SwitchBlock)
        EmitBlock(Info.SwitchBlock);
      if (Info.EndBlock)
        EmitBlock(Info.EndBlock);
    } else
      EmitStmt(S.getTryBlock());
  } else
    EmitStmt(S.getTryBlock());

  // Jump to end if there is no exception
  EmitBranchThroughCleanup(FinallyEnd);

  llvm::BasicBlock *TerminateHandler = getTerminateHandler();

  // Emit the handlers
  EmitBlock(TryHandler);

  const llvm::IntegerType *Int8Ty;
  const llvm::PointerType *PtrToInt8Ty;
  Int8Ty = llvm::Type::getInt8Ty(VMContext);
  // C string type.  Used in lots of places.
  PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty);
  llvm::Constant *Null = llvm::ConstantPointerNull::get(PtrToInt8Ty);
  llvm::SmallVector<llvm::Value*, 8> SelectorArgs;
  llvm::Value *llvm_eh_typeid_for =
    CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for);
  // Exception object
  llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc");
  llvm::Value *RethrowPtr = CreateTempAlloca(Exc->getType(), "_rethrow");

  llvm::SmallVector<llvm::Value*, 8> Args;
  Args.clear();
  SelectorArgs.push_back(Exc);
  SelectorArgs.push_back(Personality);

  bool HasCatchAll = false;
  for (unsigned i = 0; i<S.getNumHandlers(); ++i) {
    const CXXCatchStmt *C = S.getHandler(i);
    VarDecl *CatchParam = C->getExceptionDecl();
    if (CatchParam) {
      llvm::Value *EHType
        = CGM.GenerateRTTI(C->getCaughtType().getNonReferenceType());
      SelectorArgs.push_back(EHType);
    } else {
      // null indicates catch all
      SelectorArgs.push_back(Null);
      HasCatchAll = true;
    }
  }

  // We use a cleanup unless there was already a catch all.
  if (!HasCatchAll) {
    SelectorArgs.push_back(Null);
  }

  // Find which handler was matched.
  llvm::Value *Selector
    = Builder.CreateCall(llvm_eh_selector, SelectorArgs.begin(),
                         SelectorArgs.end(), "selector");
  for (unsigned i = 0; i<S.getNumHandlers(); ++i) {
    const CXXCatchStmt *C = S.getHandler(i);
    VarDecl *CatchParam = C->getExceptionDecl();
    Stmt *CatchBody = C->getHandlerBlock();

    llvm::BasicBlock *Next = 0;

    if (SelectorArgs[i+2] != Null) {
      llvm::BasicBlock *Match = createBasicBlock("match");
      Next = createBasicBlock("catch.next");
      const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext());
      llvm::Value *Id
        = Builder.CreateCall(llvm_eh_typeid_for,
                             Builder.CreateBitCast(SelectorArgs[i+2],
                                                   Int8PtrTy));
      Builder.CreateCondBr(Builder.CreateICmpEQ(Selector, Id),
                           Match, Next);
      EmitBlock(Match);
    }

    llvm::BasicBlock *MatchEnd = createBasicBlock("match.end");
    llvm::BasicBlock *MatchHandler = createBasicBlock("match.handler");

    PushCleanupBlock(MatchEnd);
    setInvokeDest(MatchHandler);

    llvm::Value *ExcObject = Builder.CreateCall(getBeginCatchFn(*this), Exc);

    {
      CleanupScope CatchScope(*this);
      // Bind the catch parameter if it exists.
      if (CatchParam) {
        QualType CatchType = CatchParam->getType().getNonReferenceType();
        setInvokeDest(TerminateHandler);
        bool WasPointer = true;
        if (!CatchType.getTypePtr()->isPointerType()) {
          if (!isa<ReferenceType>(CatchParam->getType()))
            WasPointer = false;
          CatchType = getContext().getPointerType(CatchType);
        }
        ExcObject = Builder.CreateBitCast(ExcObject, ConvertType(CatchType));
        EmitLocalBlockVarDecl(*CatchParam);
        // FIXME: we need to do this sooner so that the EH region for the
        // cleanup doesn't start until after the ctor completes, use a decl
        // init?
        CopyObject(*this, CatchParam->getType().getNonReferenceType(),
                   WasPointer, ExcObject, GetAddrOfLocalVar(CatchParam));
        setInvokeDest(MatchHandler);
      }

      EmitStmt(CatchBody);
    }

    EmitBranchThroughCleanup(FinallyEnd);

    EmitBlock(MatchHandler);

    llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc");
    // We are required to emit this call to satisfy LLVM, even
    // though we don't use the result.
    Args.clear();
    Args.push_back(Exc);
    Args.push_back(Personality);
    Args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
                                          0));
    Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end());
    Builder.CreateStore(Exc, RethrowPtr);
    EmitBranchThroughCleanup(FinallyRethrow);

    CodeGenFunction::CleanupBlockInfo Info = PopCleanupBlock();

    EmitBlock(MatchEnd);

    llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
    Builder.CreateInvoke(getEndCatchFn(*this),
                         Cont, TerminateHandler,
                         Args.begin(), Args.begin());
    EmitBlock(Cont);
    if (Info.SwitchBlock)
      EmitBlock(Info.SwitchBlock);
    if (Info.EndBlock)
      EmitBlock(Info.EndBlock);

    Exc = Builder.CreateCall(llvm_eh_exception, "exc");
    Builder.CreateStore(Exc, RethrowPtr);
    EmitBranchThroughCleanup(FinallyRethrow);

    if (Next)
      EmitBlock(Next);
  }
  if (!HasCatchAll) {
    Builder.CreateStore(Exc, RethrowPtr);
    EmitBranchThroughCleanup(FinallyRethrow);
  }

  CodeGenFunction::CleanupBlockInfo Info = PopCleanupBlock();

  setInvokeDest(PrevLandingPad);

  EmitBlock(FinallyBlock);

  if (Info.SwitchBlock)
    EmitBlock(Info.SwitchBlock);
  if (Info.EndBlock)
    EmitBlock(Info.EndBlock);

  // Branch around the rethrow code.
  EmitBranch(FinallyEnd);

  EmitBlock(FinallyRethrow);
  // FIXME: Eventually we can chain the handlers together and just do a call
  // here.
  if (getInvokeDest()) {
    llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
    Builder.CreateInvoke(getUnwindResumeOrRethrowFn(*this), Cont,
                         getInvokeDest(),
                         Builder.CreateLoad(RethrowPtr));
    EmitBlock(Cont);
  } else
    Builder.CreateCall(getUnwindResumeOrRethrowFn(*this),
                       Builder.CreateLoad(RethrowPtr));

  Builder.CreateUnreachable();

  EmitBlock(FinallyEnd);
}