// 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"); } }
// 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); }
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); }
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()); }