From 50198098b95d30dc027ac4f89e77a727b3a25635 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Thu, 2 Dec 2010 17:02:11 +0000 Subject: [PATCH] IR Gen. part of API support for __block cxx objects imported into blocks. //rdar://8594790. Will have a test case coming (as well as one sent to llvm test suite). llvm-svn: 120713 --- clang/include/clang/AST/ASTContext.h | 4 +- clang/lib/AST/ASTContext.cpp | 4 +- clang/lib/CodeGen/CGBlocks.cpp | 118 +++++++++++++-------------- clang/lib/CodeGen/CGBlocks.h | 11 ++- clang/lib/CodeGen/CGDecl.cpp | 7 +- clang/lib/CodeGen/CGExprCXX.cpp | 3 +- clang/lib/CodeGen/CodeGenFunction.h | 2 +- clang/test/CodeGen/blocks-1.c | 4 +- clang/test/CodeGenObjC/blocks-1.m | 8 +- 9 files changed, 83 insertions(+), 78 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 87a210f66195..65688619c47b 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -130,7 +130,7 @@ class ASTContext { llvm::DenseMap ObjCImpls; /// \brief Mapping from __block VarDecls to their copy initialization expr. - llvm::DenseMap BlockVarCopyInits; + llvm::DenseMap BlockVarCopyInits; /// \brief Representation of a "canonical" template template parameter that /// is used in canonical template names. @@ -1366,7 +1366,7 @@ public: void setBlockVarCopyInits(VarDecl*VD, Expr* Init); /// \brief Get the copy initialization expression of VarDecl,or NULL if /// none exists. - Expr *getBlockVarCopyInits(VarDecl*VD); + Expr *getBlockVarCopyInits(const VarDecl*VD); /// \brief Allocate an uninitialized TypeSourceInfo. /// diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index e1797665c939..1bbe08e38d48 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1010,8 +1010,8 @@ void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD, /// \brief Get the copy initialization expression of VarDecl,or NULL if /// none exists. -Expr *ASTContext::getBlockVarCopyInits(VarDecl*VD) { - llvm::DenseMap::iterator +Expr *ASTContext::getBlockVarCopyInits(const VarDecl*VD) { + llvm::DenseMap::iterator I = BlockVarCopyInits.find(VD); return (I != BlockVarCopyInits.end()) ? cast(I->second) : 0; } diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index b6cd1949ccff..510db0b1ffcf 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -1000,29 +1000,16 @@ GenerateCopyHelperFunction(const llvm::StructType *T, llvm::Value *Srcv = SrcObj; Srcv = Builder.CreateStructGEP(Srcv, index); llvm::Value *Dstv; - if (NoteForHelper[i].cxxvar_import) { - if (NoteForHelper[i].flag & BLOCK_FIELD_IS_BYREF) { - const ValueDecl *VD = NoteForHelper[i].cxxvar_import->getDecl(); - const llvm::Type *PtrStructTy - = llvm::PointerType::get(CGF.BuildByRefType(VD), 0); - Srcv = Builder.CreateLoad(Srcv); - Srcv = Builder.CreateBitCast(Srcv, PtrStructTy); - Srcv = Builder.CreateStructGEP(Srcv, CGF.getByRefValueLLVMField(VD), - VD->getNameAsString()); - - Dstv = Builder.CreateBitCast(DstObj, PtrStructTy); - Dstv = Builder.CreateStructGEP(Dstv, CGF.getByRefValueLLVMField(VD), - VD->getNameAsString()); - CGF.EmitSynthesizedCXXCopyCtor(Dstv, Srcv, - NoteForHelper[i].cxxvar_import); - } - else { - Srcv = Builder.CreateBitCast(Srcv, - llvm::PointerType::get(PtrToInt8Ty, 0)); - Dstv = Builder.CreateStructGEP(DstObj, index); - CGF.EmitSynthesizedCXXCopyCtor(Dstv, Srcv, - NoteForHelper[i].cxxvar_import); - } + if (NoteForHelper[i].cxxvar_import && + (NoteForHelper[i].flag & BLOCK_FIELD_IS_BYREF) == 0) { + // Note that cxx objects declared as __block require a + // different API. They are copy constructed in their own copy + // helper functions (see GeneratebyrefCopyHelperFunction). + Srcv = Builder.CreateBitCast(Srcv, + llvm::PointerType::get(PtrToInt8Ty, 0)); + Dstv = Builder.CreateStructGEP(DstObj, index); + CGF.EmitSynthesizedCXXCopyCtor(Dstv, Srcv, + NoteForHelper[i].cxxvar_import->getCopyConstructorExpr()); } else { Srcv = Builder.CreateBitCast(Srcv, @@ -1099,23 +1086,13 @@ GenerateDestroyHelperFunction(const llvm::StructType* T, Srcv = Builder.CreateStructGEP(Srcv, index); Srcv = Builder.CreateBitCast(Srcv, llvm::PointerType::get(PtrToInt8Ty, 0)); - if (NoteForHelper[i].cxxvar_import) { + if (NoteForHelper[i].cxxvar_import && + (NoteForHelper[i].flag & BLOCK_FIELD_IS_BYREF) == 0) { const BlockDeclRefExpr *BDRE = NoteForHelper[i].cxxvar_import; const Expr *E = BDRE->getCopyConstructorExpr(); QualType ClassTy = E->getType(); QualType PtrClassTy = getContext().getPointerType(ClassTy); const llvm::Type *t = CGM.getTypes().ConvertType(PtrClassTy); - - if (NoteForHelper[i].flag & BLOCK_FIELD_IS_BYREF) { - const ValueDecl *VD = NoteForHelper[i].cxxvar_import->getDecl(); - const llvm::Type *PtrStructTy - = llvm::PointerType::get(CGF.BuildByRefType(VD), 0); - Srcv = Builder.CreateLoad(Srcv); - Srcv = Builder.CreateBitCast(Srcv, PtrStructTy); - Srcv = Builder.CreateStructGEP(Srcv, CGF.getByRefValueLLVMField(VD), - VD->getNameAsString()); - - } Srcv = Builder.CreateBitCast(Srcv, t); CGF.PushDestructorCleanup(ClassTy, Srcv); } @@ -1144,7 +1121,8 @@ llvm::Constant *BlockFunction::BuildDestroyHelper(const llvm::StructType *T, } llvm::Constant *BlockFunction:: -GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) { +GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag, + const VarDecl *BD) { QualType R = getContext().VoidTy; FunctionArgList Args; @@ -1172,10 +1150,10 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) { // internal linkage. llvm::Function *Fn = llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, - "__Block_byref_id_object_copy_", &CGM.getModule()); + "__Block_byref_object_copy_", &CGM.getModule()); IdentifierInfo *II - = &CGM.getContext().Idents.get("__Block_byref_id_object_copy_"); + = &CGM.getContext().Idents.get("__Block_byref_object_copy_"); FunctionDecl *FD = FunctionDecl::Create(getContext(), getContext().getTranslationUnitDecl(), @@ -1190,22 +1168,30 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) { V = Builder.CreateBitCast(V, llvm::PointerType::get(T, 0)); V = Builder.CreateLoad(V); V = Builder.CreateStructGEP(V, 6, "x"); - llvm::Value *DstObj = Builder.CreateBitCast(V, PtrToInt8Ty); + llvm::Value *DstObj = V; // src->x V = CGF.GetAddrOfLocalVar(Src); V = Builder.CreateLoad(V); V = Builder.CreateBitCast(V, T); V = Builder.CreateStructGEP(V, 6, "x"); - V = Builder.CreateBitCast(V, llvm::PointerType::get(PtrToInt8Ty, 0)); - llvm::Value *SrcObj = Builder.CreateLoad(V); - - flag |= BLOCK_BYREF_CALLER; - - llvm::Value *N = llvm::ConstantInt::get(CGF.Int32Ty, flag); - llvm::Value *F = CGM.getBlockObjectAssign(); - Builder.CreateCall3(F, DstObj, SrcObj, N); - + + if (flag & BLOCK_HAS_CXX_OBJ) { + assert (BD && "VarDecl is null - GeneratebyrefCopyHelperFunction"); + llvm::Value *SrcObj = V; + CGF.EmitSynthesizedCXXCopyCtor(DstObj, SrcObj, + getContext().getBlockVarCopyInits(BD)); + } + else { + DstObj = Builder.CreateBitCast(DstObj, PtrToInt8Ty); + V = Builder.CreateBitCast(V, llvm::PointerType::get(PtrToInt8Ty, 0)); + llvm::Value *SrcObj = Builder.CreateLoad(V); + flag |= BLOCK_BYREF_CALLER; + llvm::Value *N = llvm::ConstantInt::get(CGF.Int32Ty, flag); + llvm::Value *F = CGM.getBlockObjectAssign(); + Builder.CreateCall3(F, DstObj, SrcObj, N); + } + CGF.FinishFunction(); return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty); @@ -1213,7 +1199,8 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) { llvm::Constant * BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T, - int flag) { + int flag, + const VarDecl *BD) { QualType R = getContext().VoidTy; FunctionArgList Args; @@ -1235,11 +1222,11 @@ BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T, // internal linkage. llvm::Function *Fn = llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, - "__Block_byref_id_object_dispose_", + "__Block_byref_object_dispose_", &CGM.getModule()); IdentifierInfo *II - = &CGM.getContext().Idents.get("__Block_byref_id_object_dispose_"); + = &CGM.getContext().Idents.get("__Block_byref_object_dispose_"); FunctionDecl *FD = FunctionDecl::Create(getContext(), getContext().getTranslationUnitDecl(), @@ -1253,18 +1240,28 @@ BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T, V = Builder.CreateBitCast(V, llvm::PointerType::get(T, 0)); V = Builder.CreateLoad(V); V = Builder.CreateStructGEP(V, 6, "x"); - V = Builder.CreateBitCast(V, llvm::PointerType::get(PtrToInt8Ty, 0)); - V = Builder.CreateLoad(V); + if (flag & BLOCK_HAS_CXX_OBJ) { + EHScopeStack::stable_iterator CleanupDepth = CGF.EHStack.stable_begin(); + assert (BD && "VarDecl is null - GeneratebyrefDestroyHelperFunction"); + QualType ClassTy = BD->getType(); + CGF.PushDestructorCleanup(ClassTy, V); + CGF.PopCleanupBlocks(CleanupDepth); + } + else { + V = Builder.CreateBitCast(V, llvm::PointerType::get(PtrToInt8Ty, 0)); + V = Builder.CreateLoad(V); - flag |= BLOCK_BYREF_CALLER; - BuildBlockRelease(V, flag); + flag |= BLOCK_BYREF_CALLER; + BuildBlockRelease(V, flag); + } CGF.FinishFunction(); return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty); } llvm::Constant *BlockFunction::BuildbyrefCopyHelper(const llvm::Type *T, - int Flag, unsigned Align) { + int Flag, unsigned Align, + const VarDecl *BD) { // All alignments below that of pointer alignment collapse down to just // pointer alignment, as we always have at least that much alignment to begin // with. @@ -1277,12 +1274,14 @@ llvm::Constant *BlockFunction::BuildbyrefCopyHelper(const llvm::Type *T, llvm::Constant *&Entry = CGM.AssignCache[Kind]; if (Entry) return Entry; - return Entry = CodeGenFunction(CGM).GeneratebyrefCopyHelperFunction(T, Flag); + return Entry = + CodeGenFunction(CGM).GeneratebyrefCopyHelperFunction(T, Flag, BD); } llvm::Constant *BlockFunction::BuildbyrefDestroyHelper(const llvm::Type *T, int Flag, - unsigned Align) { + unsigned Align, + const VarDecl *BD) { // All alignments below that of pointer alignment collpase down to just // pointer alignment, as we always have at least that much alignment to begin // with. @@ -1295,7 +1294,8 @@ llvm::Constant *BlockFunction::BuildbyrefDestroyHelper(const llvm::Type *T, llvm::Constant *&Entry = CGM.DestroyCache[Kind]; if (Entry) return Entry; - return Entry=CodeGenFunction(CGM).GeneratebyrefDestroyHelperFunction(T, Flag); + return Entry = + CodeGenFunction(CGM).GeneratebyrefDestroyHelperFunction(T, Flag, BD); } void BlockFunction::BuildBlockRelease(llvm::Value *V, int flag) { diff --git a/clang/lib/CodeGen/CGBlocks.h b/clang/lib/CodeGen/CGBlocks.h index f82ce117b349..a1453f681614 100644 --- a/clang/lib/CodeGen/CGBlocks.h +++ b/clang/lib/CodeGen/CGBlocks.h @@ -189,13 +189,16 @@ public: llvm::Constant *BuildDestroyHelper(const llvm::StructType *, std::vector *); - llvm::Constant *GeneratebyrefCopyHelperFunction(const llvm::Type *, int flag); - llvm::Constant *GeneratebyrefDestroyHelperFunction(const llvm::Type *T, int); + llvm::Constant *GeneratebyrefCopyHelperFunction(const llvm::Type *, int flag, + const VarDecl *BD); + llvm::Constant *GeneratebyrefDestroyHelperFunction(const llvm::Type *T, + int flag, + const VarDecl *BD); llvm::Constant *BuildbyrefCopyHelper(const llvm::Type *T, int flag, - unsigned Align); + unsigned Align, const VarDecl *BD); llvm::Constant *BuildbyrefDestroyHelper(const llvm::Type *T, int flag, - unsigned Align); + unsigned Align, const VarDecl *BD); void BuildBlockRelease(llvm::Value *DeclPtr, int flag = BLOCK_FIELD_IS_BYREF); diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 4032bedbfc80..9490769407d9 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -756,6 +756,9 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D, Ty->isObjCObjectPointerType()) { flag |= BLOCK_FIELD_IS_OBJECT; flags |= BLOCK_HAS_COPY_DISPOSE; + } else if (getContext().getBlockVarCopyInits(&D)) { + flag |= BLOCK_HAS_CXX_OBJ; + flags |= BLOCK_HAS_COPY_DISPOSE; } // FIXME: Someone double check this. @@ -781,12 +784,12 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D, SynthesizeCopyDisposeHelpers = true; llvm::Value *copy_helper = Builder.CreateStructGEP(DeclPtr, 4); Builder.CreateStore(BuildbyrefCopyHelper(DeclPtr->getType(), flag, - Align.getQuantity()), + Align.getQuantity(), &D), copy_helper); llvm::Value *destroy_helper = Builder.CreateStructGEP(DeclPtr, 5); Builder.CreateStore(BuildbyrefDestroyHelper(DeclPtr->getType(), flag, - Align.getQuantity()), + Align.getQuantity(), &D), destroy_helper); } } diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 66a07454ae2f..883e666a8cd3 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -344,8 +344,7 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E, void CodeGenFunction::EmitSynthesizedCXXCopyCtor(llvm::Value *Dest, llvm::Value *Src, - const BlockDeclRefExpr *BDRE) { - const Expr *Exp = BDRE->getCopyConstructorExpr(); + const Expr *Exp) { if (const CXXExprWithTemporaries *E = dyn_cast(Exp)) Exp = E->getSubExpr(); assert(isa(Exp) && diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 616c227ffbe1..e8de03a56ada 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1659,7 +1659,7 @@ public: void EmitCXXConstructExpr(const CXXConstructExpr *E, AggValueSlot Dest); void EmitSynthesizedCXXCopyCtor(llvm::Value *Dest, llvm::Value *Src, - const BlockDeclRefExpr *BDRE); + const Expr *Exp); RValue EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E, AggValueSlot Slot =AggValueSlot::ignored()); diff --git a/clang/test/CodeGen/blocks-1.c b/clang/test/CodeGen/blocks-1.c index 71b4de8beff5..1eb13063c68d 100644 --- a/clang/test/CodeGen/blocks-1.c +++ b/clang/test/CodeGen/blocks-1.c @@ -2,8 +2,8 @@ // RUN: grep "_Block_object_dispose" %t | count 17 // RUN: grep "__copy_helper_block_" %t | count 16 // RUN: grep "__destroy_helper_block_" %t | count 16 -// RUN: grep "__Block_byref_id_object_copy_" %t | count 2 -// RUN: grep "__Block_byref_id_object_dispose_" %t | count 2 +// RUN: grep "__Block_byref_object_copy_" %t | count 2 +// RUN: grep "__Block_byref_object_dispose_" %t | count 2 // RUN: grep "i32 135)" %t | count 2 // RUN: grep "_Block_object_assign" %t | count 10 diff --git a/clang/test/CodeGenObjC/blocks-1.m b/clang/test/CodeGenObjC/blocks-1.m index 1ac9c30c8a00..55ce38fe9ef9 100644 --- a/clang/test/CodeGenObjC/blocks-1.m +++ b/clang/test/CodeGenObjC/blocks-1.m @@ -2,8 +2,8 @@ // RUN: grep "_Block_object_dispose" %t | count 6 // RUN: grep "__copy_helper_block_" %t | count 4 // RUN: grep "__destroy_helper_block_" %t | count 4 -// RUN: grep "__Block_byref_id_object_copy_" %t | count 2 -// RUN: grep "__Block_byref_id_object_dispose_" %t | count 2 +// RUN: grep "__Block_byref_object_copy_" %t | count 2 +// RUN: grep "__Block_byref_object_dispose_" %t | count 2 // RUN: grep "i32 135)" %t | count 0 // RUN: grep "_Block_object_assign" %t | count 4 // RUN: grep "objc_read_weak" %t | count 2 @@ -12,8 +12,8 @@ // RUN: grep "_Block_object_dispose" %t | count 6 // RUN: grep "__copy_helper_block_" %t | count 4 // RUN: grep "__destroy_helper_block_" %t | count 4 -// RUN: grep "__Block_byref_id_object_copy_" %t | count 2 -// RUN: grep "__Block_byref_id_object_dispose_" %t | count 2 +// RUN: grep "__Block_byref_object_copy_" %t | count 2 +// RUN: grep "__Block_byref_object_dispose_" %t | count 2 // RUN: grep "i32 135)" %t | count 0 // RUN: grep "_Block_object_assign" %t | count 4 // RUN: grep "objc_read_weak" %t | count 2