Example #1
0
// CopyObject - Utility to copy an object.  Calls copy constructor as necessary.
// DestPtr is casted to the right type.
static void CopyObject(CodeGenFunction &CGF, const Expr *E, 
                       llvm::Value *DestPtr, llvm::Value *ExceptionPtrPtr) {
  QualType ObjectType = E->getType();

  // Store the throw exception in the exception object.
  if (!CGF.hasAggregateLLVMType(ObjectType)) {
    llvm::Value *Value = CGF.EmitScalarExpr(E);
    const llvm::Type *ValuePtrTy = Value->getType()->getPointerTo();

    CGF.Builder.CreateStore(Value, 
                            CGF.Builder.CreateBitCast(DestPtr, ValuePtrTy));
  } else {
    const llvm::Type *Ty = CGF.ConvertType(ObjectType)->getPointerTo();
    const CXXRecordDecl *RD =
      cast<CXXRecordDecl>(ObjectType->getAs<RecordType>()->getDecl());
    
    llvm::Value *This = CGF.Builder.CreateBitCast(DestPtr, Ty);
    if (RD->hasTrivialCopyConstructor()) {
      CGF.EmitAggExpr(E, This, false);
    } else if (CXXConstructorDecl *CopyCtor
               = RD->getCopyConstructor(CGF.getContext(), 0)) {
      llvm::BasicBlock *PrevLandingPad = CGF.getInvokeDest();
      if (CGF.Exceptions) {
        CodeGenFunction::EHCleanupBlock Cleanup(CGF);
        llvm::Constant *FreeExceptionFn = getFreeExceptionFn(CGF);
        
        // Load the exception pointer.
        llvm::Value *ExceptionPtr = CGF.Builder.CreateLoad(ExceptionPtrPtr);
        CGF.Builder.CreateCall(FreeExceptionFn, ExceptionPtr);
      }

      llvm::Value *Src = CGF.EmitLValue(E).getAddress();
      CGF.setInvokeDest(PrevLandingPad);

      llvm::BasicBlock *TerminateHandler = CGF.getTerminateHandler();
      PrevLandingPad = CGF.getInvokeDest();
      CGF.setInvokeDest(TerminateHandler);

      // Stolen from EmitClassAggrMemberwiseCopy
      llvm::Value *Callee = CGF.CGM.GetAddrOfCXXConstructor(CopyCtor,
                                                            Ctor_Complete);
      CallArgList CallArgs;
      CallArgs.push_back(std::make_pair(RValue::get(This),
                                      CopyCtor->getThisType(CGF.getContext())));

      // Push the Src ptr.
      CallArgs.push_back(std::make_pair(RValue::get(Src),
                                        CopyCtor->getParamDecl(0)->getType()));
      QualType ResultType =
        CopyCtor->getType()->getAs<FunctionType>()->getResultType();
      CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(ResultType, CallArgs),
                   Callee, CallArgs, CopyCtor);
      CGF.setInvokeDest(PrevLandingPad);
    } else
      llvm_unreachable("uncopyable object");
  }
}
Example #2
0
// CopyObject - Utility to copy an object.  Calls copy constructor as necessary.
// N is casted to the right type.
static void CopyObject(CodeGenFunction &CGF, QualType ObjectType,
                       bool WasPointer, bool WasPointerReference,
                       llvm::Value *E, llvm::Value *N) {
  // Store the throw exception in the exception object.
  if (WasPointer || !CGF.hasAggregateLLVMType(ObjectType)) {
    llvm::Value *Value = E;
    if (!WasPointer)
      Value = CGF.Builder.CreateLoad(Value);
    const llvm::Type *ValuePtrTy = Value->getType()->getPointerTo(0);
    if (WasPointerReference) {
      llvm::Value *Tmp = CGF.CreateTempAlloca(Value->getType(), "catch.param");
      CGF.Builder.CreateStore(Value, Tmp);
      Value = Tmp;
      ValuePtrTy = Value->getType()->getPointerTo(0);
    }
    N = CGF.Builder.CreateBitCast(N, ValuePtrTy);
    CGF.Builder.CreateStore(Value, N);
  } else {
    const llvm::Type *Ty = CGF.ConvertType(ObjectType)->getPointerTo(0);
    const CXXRecordDecl *RD;
    RD = cast<CXXRecordDecl>(ObjectType->getAs<RecordType>()->getDecl());
    llvm::Value *This = CGF.Builder.CreateBitCast(N, Ty);
    if (RD->hasTrivialCopyConstructor()) {
      CGF.EmitAggregateCopy(This, E, ObjectType);
    } else if (CXXConstructorDecl *CopyCtor
               = RD->getCopyConstructor(CGF.getContext(), 0)) {
      llvm::Value *Src = E;

      // Stolen from EmitClassAggrMemberwiseCopy
      llvm::Value *Callee = CGF.CGM.GetAddrOfCXXConstructor(CopyCtor,
                                                            Ctor_Complete);
      CallArgList CallArgs;
      CallArgs.push_back(std::make_pair(RValue::get(This),
                                      CopyCtor->getThisType(CGF.getContext())));

      // Push the Src ptr.
      CallArgs.push_back(std::make_pair(RValue::get(Src),
                                        CopyCtor->getParamDecl(0)->getType()));

      const FunctionProtoType *FPT
        = CopyCtor->getType()->getAs<FunctionProtoType>();
      CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(CallArgs, FPT),
                   Callee, ReturnValueSlot(), CallArgs, CopyCtor);
    } else
      llvm_unreachable("uncopyable object");
  }
}
void ItaniumCXXABI::ReadArrayCookie(CodeGenFunction &CGF,
                                    llvm::Value *Ptr,
                                    const CXXDeleteExpr *expr,
                                    QualType ElementType,
                                    llvm::Value *&NumElements,
                                    llvm::Value *&AllocPtr,
                                    CharUnits &CookieSize) {
  // Derive a char* in the same address space as the pointer.
  unsigned AS = cast<llvm::PointerType>(Ptr->getType())->getAddressSpace();
  llvm::Type *CharPtrTy = CGF.Builder.getInt8Ty()->getPointerTo(AS);

  // If we don't need an array cookie, bail out early.
  if (!NeedsArrayCookie(expr, ElementType)) {
    AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy);
    NumElements = 0;
    CookieSize = CharUnits::Zero();
    return;
  }

  QualType SizeTy = getContext().getSizeType();
  CharUnits SizeSize = getContext().getTypeSizeInChars(SizeTy);
  llvm::Type *SizeLTy = CGF.ConvertType(SizeTy);
  
  CookieSize
    = std::max(SizeSize, getContext().getTypeAlignInChars(ElementType));

  CharUnits NumElementsOffset = CookieSize - SizeSize;

  // Compute the allocated pointer.
  AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy);
  AllocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr,
                                                    -CookieSize.getQuantity());

  llvm::Value *NumElementsPtr = AllocPtr;
  if (!NumElementsOffset.isZero())
    NumElementsPtr =
      CGF.Builder.CreateConstInBoundsGEP1_64(NumElementsPtr,
                                             NumElementsOffset.getQuantity());
  NumElementsPtr = 
    CGF.Builder.CreateBitCast(NumElementsPtr, SizeLTy->getPointerTo(AS));
  NumElements = CGF.Builder.CreateLoad(NumElementsPtr);
}
void ARMCXXABI::ReadArrayCookie(CodeGenFunction &CGF,
                                llvm::Value *Ptr,
                                const CXXDeleteExpr *expr,
                                QualType ElementType,
                                llvm::Value *&NumElements,
                                llvm::Value *&AllocPtr,
                                CharUnits &CookieSize) {
  // Derive a char* in the same address space as the pointer.
  unsigned AS = cast<llvm::PointerType>(Ptr->getType())->getAddressSpace();
  llvm::Type *CharPtrTy = CGF.Builder.getInt8Ty()->getPointerTo(AS);

  // If we don't need an array cookie, bail out early.
  if (!NeedsArrayCookie(expr, ElementType)) {
    AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy);
    NumElements = 0;
    CookieSize = CharUnits::Zero();
    return;
  }

  QualType SizeTy = getContext().getSizeType();
  CharUnits SizeSize = getContext().getTypeSizeInChars(SizeTy);
  llvm::Type *SizeLTy = CGF.ConvertType(SizeTy);
  
  // The cookie size is always 2 * sizeof(size_t).
  CookieSize = 2 * SizeSize;

  // The allocated pointer is the input ptr, minus that amount.
  AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy);
  AllocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr,
                                               -CookieSize.getQuantity());

  // The number of elements is at offset sizeof(size_t) relative to that.
  llvm::Value *NumElementsPtr
    = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr,
                                             SizeSize.getQuantity());
  NumElementsPtr = 
    CGF.Builder.CreateBitCast(NumElementsPtr, SizeLTy->getPointerTo(AS));
  NumElements = CGF.Builder.CreateLoad(NumElementsPtr);
}
Example #5
0
RValue EmitUPCCall(CodeGenFunction &CGF,
                   llvm::StringRef Name,
                   QualType ResultTy,
                   const CallArgList& Args) {
  ASTContext &Context = CGF.CGM.getContext();
  llvm::SmallVector<QualType, 5> ArgTypes;

  for (CallArgList::const_iterator iter = Args.begin(),
         end = Args.end(); iter != end; ++iter) {
    ArgTypes.push_back(iter->Ty);
  }

  QualType FuncType =
    Context.getFunctionType(ResultTy,
                            ArgTypes,
                            FunctionProtoType::ExtProtoInfo());
    const CGFunctionInfo &Info =
      CGF.getTypes().arrangeFreeFunctionCall(Args, FuncType->castAs<FunctionType>());
    llvm::FunctionType * FTy =
      cast<llvm::FunctionType>(CGF.ConvertType(FuncType));
    llvm::Value * Fn = CGF.CGM.CreateRuntimeFunction(FTy, Name);

    return CGF.EmitCall(Info, Fn, ReturnValueSlot(), Args);
}
Example #6
0
void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
                                     const ObjCAtTryStmt &S,
                                     llvm::Constant *beginCatchFn,
                                     llvm::Constant *endCatchFn,
                                     llvm::Constant *exceptionRethrowFn) {
  // Jump destination for falling out of catch bodies.
  CodeGenFunction::JumpDest Cont;
  if (S.getNumCatchStmts())
    Cont = CGF.getJumpDestInCurrentScope("eh.cont");

  CodeGenFunction::FinallyInfo FinallyInfo;
  if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt())
    FinallyInfo.enter(CGF, Finally->getFinallyBody(),
                      beginCatchFn, endCatchFn, exceptionRethrowFn);

  SmallVector<CatchHandler, 8> Handlers;

  // Enter the catch, if there is one.
  if (S.getNumCatchStmts()) {
    for (unsigned I = 0, N = S.getNumCatchStmts(); I != N; ++I) {
      const ObjCAtCatchStmt *CatchStmt = S.getCatchStmt(I);
      const VarDecl *CatchDecl = CatchStmt->getCatchParamDecl();

      Handlers.push_back(CatchHandler());
      CatchHandler &Handler = Handlers.back();
      Handler.Variable = CatchDecl;
      Handler.Body = CatchStmt->getCatchBody();
      Handler.Block = CGF.createBasicBlock("catch");

      // @catch(...) always matches.
      if (!CatchDecl) {
        Handler.TypeInfo = 0; // catch-all
        // Don't consider any other catches.
        break;
      }

      Handler.TypeInfo = GetEHType(CatchDecl->getType());
    }

    EHCatchScope *Catch = CGF.EHStack.pushCatch(Handlers.size());
    for (unsigned I = 0, E = Handlers.size(); I != E; ++I)
      Catch->setHandler(I, Handlers[I].TypeInfo, Handlers[I].Block);
  }
  
  // Emit the try body.
  CGF.EmitStmt(S.getTryBody());

  // Leave the try.
  if (S.getNumCatchStmts())
    CGF.popCatchScope();

  // Remember where we were.
  CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();

  // Emit the handlers.
  for (unsigned I = 0, E = Handlers.size(); I != E; ++I) {
    CatchHandler &Handler = Handlers[I];

    CGF.EmitBlock(Handler.Block);
    llvm::Value *RawExn = CGF.getExceptionFromSlot();

    // Enter the catch.
    llvm::Value *Exn = RawExn;
    if (beginCatchFn) {
      Exn = CGF.Builder.CreateCall(beginCatchFn, RawExn, "exn.adjusted");
      cast<llvm::CallInst>(Exn)->setDoesNotThrow();
    }

    CodeGenFunction::RunCleanupsScope cleanups(CGF);

    if (endCatchFn) {
      // Add a cleanup to leave the catch.
      bool EndCatchMightThrow = (Handler.Variable == 0);

      CGF.EHStack.pushCleanup<CallObjCEndCatch>(NormalAndEHCleanup,
                                                EndCatchMightThrow,
                                                endCatchFn);
    }

    // Bind the catch parameter if it exists.
    if (const VarDecl *CatchParam = Handler.Variable) {
      llvm::Type *CatchType = CGF.ConvertType(CatchParam->getType());
      llvm::Value *CastExn = CGF.Builder.CreateBitCast(Exn, CatchType);

      CGF.EmitAutoVarDecl(*CatchParam);
      CGF.Builder.CreateStore(CastExn, CGF.GetAddrOfLocalVar(CatchParam));
    }

    CGF.ObjCEHValueStack.push_back(Exn);
    CGF.EmitStmt(Handler.Body);
    CGF.ObjCEHValueStack.pop_back();

    // Leave any cleanups associated with the catch.
    cleanups.ForceCleanup();

    CGF.EmitBranchThroughCleanup(Cont);
  }  

  // Go back to the try-statement fallthrough.
  CGF.Builder.restoreIP(SavedIP);

  // Pop out of the finally.
  if (S.getFinallyStmt())
    FinallyInfo.exit(CGF);

  if (Cont.isValid())
    CGF.EmitBlock(Cont.getBlock());
}