diff options
-rw-r--r-- | lib/CodeGen/CGBlocks.cpp | 104 | ||||
-rw-r--r-- | lib/CodeGen/CGBlocks.h | 46 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 24 | ||||
-rw-r--r-- | test/CodeGen/blocks-1.c | 2 |
6 files changed, 128 insertions, 52 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 3b602a0a1b..8020a8b26f 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -34,7 +34,8 @@ Enable__block("f__block", llvm::cl::init(false)); llvm::Constant *CodeGenFunction:: -BuildDescriptorBlockDecl(uint64_t Size, const llvm::Type* Ty) { +BuildDescriptorBlockDecl(uint64_t Size, const llvm::StructType* Ty, + std::vector<HelperInfo> *NoteForHelper) { const llvm::Type *UnsignedLongTy = CGM.getTypes().ConvertType(getContext().UnsignedLongTy); llvm::Constant *C; @@ -53,10 +54,10 @@ BuildDescriptorBlockDecl(uint64_t Size, const llvm::Type* Ty) { if (BlockHasCopyDispose) { // copy_func_helper_decl - Elts.push_back(BuildCopyHelper(Ty)); + Elts.push_back(BuildCopyHelper(Ty, *NoteForHelper)); // destroy_func_decl - Elts.push_back(BuildDestroyHelper(Ty)); + Elts.push_back(BuildDestroyHelper(Ty, *NoteForHelper)); } C = llvm::ConstantStruct::get(Elts); @@ -183,7 +184,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { if (subBlockDeclRefDecls.size() == 0) { // __descriptor - Elts[4] = BuildDescriptorBlockDecl(subBlockSize, 0); + Elts[4] = BuildDescriptorBlockDecl(subBlockSize, 0, 0); // Optimize to being a global block. Elts[0] = CGM.getNSConcreteGlobalBlock(); @@ -202,8 +203,9 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { } std::vector<const llvm::Type *> Types(5+subBlockDeclRefDecls.size()); - for (int i=0; i<5; ++i) + for (int i=0; i<4; ++i) Types[i] = Elts[i]->getType(); + Types[4] = PtrToInt8Ty; for (unsigned i=0; i < subBlockDeclRefDecls.size(); ++i) { const Expr *E = subBlockDeclRefDecls[i]; @@ -216,13 +218,16 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { Types[i+5] = ConvertType(Ty); } - llvm::Type *Ty = llvm::StructType::get(Types, true); + llvm::StructType *Ty = llvm::StructType::get(Types, true); llvm::AllocaInst *A = CreateTempAlloca(Ty); A->setAlignment(subBlockAlign); V = A; - for (unsigned i=0; i<5; ++i) + std::vector<HelperInfo> NoteForHelper(subBlockDeclRefDecls.size()); + int helpersize = 0; + + for (unsigned i=0; i<4; ++i) Builder.CreateStore(Elts[i], Builder.CreateStructGEP(V, i, "block.tmp")); for (unsigned i=0; i < subBlockDeclRefDecls.size(); ++i) @@ -240,15 +245,24 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { VD = BDRE->getDecl(); llvm::Value* Addr = Builder.CreateStructGEP(V, i+5, "tmp"); - // FIXME: I want a better way to do this. + NoteForHelper[helpersize].index = i+5; + NoteForHelper[helpersize].RequiresCopying = BlockRequiresCopying(VD->getType()); + NoteForHelper[helpersize].flag + = VD->getType()->isBlockPointerType() ? BLOCK_FIELD_IS_BLOCK : BLOCK_FIELD_IS_OBJECT; + if (LocalDeclMap[VD]) { if (BDRE->isByRef()) { + // FIXME: For only local, or all byrefs? + NoteForHelper[helpersize].flag = BLOCK_FIELD_IS_BYREF | + (0?BLOCK_FIELD_IS_WEAK : 0); + // FIXME: Add weak support const llvm::Type *Ty = Types[i+5]; llvm::Value *Loc = LocalDeclMap[VD]; Loc = Builder.CreateStructGEP(Loc, 1, "forwarding"); Loc = Builder.CreateLoad(Loc, false); Loc = Builder.CreateBitCast(Loc, Ty); Builder.CreateStore(Loc, Addr); + ++helpersize; continue; } else E = new (getContext()) DeclRefExpr (cast<NamedDecl>(VD), @@ -261,6 +275,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { getContext().getPointerType(E->getType()), SourceLocation()); } + ++helpersize; RValue r = EmitAnyExpr(E, Addr, false); if (r.isScalar()) { @@ -296,9 +311,13 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { // FIXME: Ensure that the offset created by the backend for // the struct matches the previously computed offset in BlockDecls. } + NoteForHelper.resize(helpersize); // __descriptor - Elts[4] = BuildDescriptorBlockDecl(subBlockSize, Ty); + llvm::Value *Descriptor = BuildDescriptorBlockDecl(subBlockSize, Ty, + &NoteForHelper); + Descriptor = Builder.CreateBitCast(Descriptor, PtrToInt8Ty); + Builder.CreateStore(Descriptor, Builder.CreateStructGEP(V, 4, "block.tmp")); } QualType BPT = BE->getType(); @@ -636,7 +655,7 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr, return Fn; } -uint64_t CodeGenFunction::getBlockOffset(const BlockDeclRefExpr *BDRE) { +uint64_t BlockFunction::getBlockOffset(const BlockDeclRefExpr *BDRE) { const ValueDecl *D = dyn_cast<ValueDecl>(BDRE->getDecl()); uint64_t Size = getContext().getTypeSize(D->getType()) / 8; @@ -675,15 +694,20 @@ uint64_t CodeGenFunction::getBlockOffset(const BlockDeclRefExpr *BDRE) { return BlockOffset-Size; } -llvm::Constant *BlockFunction::GenerateCopyHelperFunction(const llvm::Type *Ty) { +llvm::Constant *BlockFunction:: +GenerateCopyHelperFunction(bool BlockHasCopyDispose, const llvm::StructType *T, + std::vector<HelperInfo> &NoteForHelper) { QualType R = getContext().VoidTy; FunctionArgList Args; // FIXME: This leaks + ImplicitParamDecl *Dst = + ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, + getContext().getPointerType(getContext().VoidTy)); + Args.push_back(std::make_pair(Dst, Dst->getType())); ImplicitParamDecl *Src = ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, getContext().getPointerType(getContext().VoidTy)); - Args.push_back(std::make_pair(Src, Src->getType())); const CGFunctionInfo &FI = @@ -707,14 +731,46 @@ llvm::Constant *BlockFunction::GenerateCopyHelperFunction(const llvm::Type *Ty) FunctionDecl::Static, false, true); CGF.StartFunction(FD, R, Fn, Args, SourceLocation()); - // EmitStmt(BExpr->getBody()); + + llvm::Value *SrcObj = CGF.GetAddrOfLocalVar(Src); + llvm::Type *PtrPtrT; + PtrPtrT = llvm::PointerType::get(llvm::PointerType::get(T, 0), 0); + SrcObj = Builder.CreateBitCast(SrcObj, PtrPtrT); + SrcObj = Builder.CreateLoad(SrcObj); + + llvm::Value *DstObj = CGF.GetAddrOfLocalVar(Dst); + DstObj = Builder.CreateBitCast(DstObj, llvm::PointerType::get(T, 0)); + + for (unsigned i=0; i < NoteForHelper.size(); ++i) { + int flag = NoteForHelper[i].flag; + int index = NoteForHelper[i].index; + + if ((NoteForHelper[i].flag & BLOCK_FIELD_IS_BYREF) + || NoteForHelper[i].RequiresCopying) { + llvm::Value *Srcv = SrcObj; + Srcv = Builder.CreateStructGEP(Srcv, index); + Srcv = Builder.CreateBitCast(Srcv, + llvm::PointerType::get(PtrToInt8Ty, 0)); + Srcv = Builder.CreateLoad(Srcv); + + llvm::Value *Dstv = Builder.CreateStructGEP(DstObj, index); + Dstv = Builder.CreateBitCast(Dstv, PtrToInt8Ty); + + llvm::Value *N = llvm::ConstantInt::get(llvm::Type::Int32Ty, flag); + llvm::Value *F = getBlockObjectAssign(); + Builder.CreateCall3(F, Dstv, Srcv, N); + } + } + CGF.FinishFunction(); return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty); } llvm::Constant *BlockFunction:: -GenerateDestroyHelperFunction(const llvm::Type* Ty) { +GenerateDestroyHelperFunction(bool BlockHasCopyDispose, + const llvm::StructType* T, + std::vector<HelperInfo> &NoteForHelper) { QualType R = getContext().VoidTy; FunctionArgList Args; @@ -752,12 +808,16 @@ GenerateDestroyHelperFunction(const llvm::Type* Ty) { return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty); } -llvm::Constant *BlockFunction::BuildCopyHelper(const llvm::Type *Ty) { - return CodeGenFunction(CGM).GenerateCopyHelperFunction(Ty); +llvm::Constant *BlockFunction::BuildCopyHelper(const llvm::StructType *T, + std::vector<HelperInfo> &NoteForHelper) { + return CodeGenFunction(CGM).GenerateCopyHelperFunction(BlockHasCopyDispose, + T, NoteForHelper); } -llvm::Constant *BlockFunction::BuildDestroyHelper(const llvm::Type *Ty) { - return CodeGenFunction(CGM).GenerateDestroyHelperFunction(Ty); +llvm::Constant *BlockFunction::BuildDestroyHelper(const llvm::StructType *T, + std::vector<HelperInfo> &NoteForHelper) { + return CodeGenFunction(CGM).GenerateDestroyHelperFunction(BlockHasCopyDispose, + T, NoteForHelper); } llvm::Constant *BlockFunction:: @@ -924,3 +984,11 @@ void BlockFunction::BuildBlockRelease(llvm::Value *V, int flag) { } ASTContext &BlockFunction::getContext() const { return CGM.getContext(); } + +BlockFunction::BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf, + CGBuilderTy &B) + : CGM(cgm), CGF(cgf), Builder(B) { + PtrToInt8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + + BlockHasCopyDispose = false; +} diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h index 5d6c089923..3eca891289 100644 --- a/lib/CodeGen/CGBlocks.h +++ b/lib/CodeGen/CGBlocks.h @@ -103,7 +103,8 @@ public: : Context(C), TheModule(M), TheTargetData(TD), Types(T), CGM(CodeGen), NSConcreteGlobalBlock(0), NSConcreteStackBlock(0), BlockDescriptorType(0), - GenericBlockLiteralType(0), BlockObjectAssign(0), BlockObjectDispose(0) { + GenericBlockLiteralType(0), GenericExtendedBlockLiteralType(0), + BlockObjectAssign(0), BlockObjectDispose(0) { Block.GlobalUniqueCount = 0; PtrToInt8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); } @@ -116,6 +117,12 @@ class BlockFunction : public BlockBase { public: const llvm::Type *PtrToInt8Ty; + struct HelperInfo { + int index; + int flag; + bool RequiresCopying; + }; + enum { BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)), block, ... */ @@ -150,19 +157,40 @@ public: CGBuilderTy &Builder; - BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf, CGBuilderTy &B) - : CGM(cgm), CGF(cgf), Builder(B) { - PtrToInt8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); - } + BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf, CGBuilderTy &B); + + /// BlockOffset - The offset in bytes for the next allocation of an + /// imported block variable. + uint64_t BlockOffset; + /// BlockAlign - Maximal alignment needed for the Block expressed in bytes. + uint64_t BlockAlign; + + /// getBlockOffset - Allocate an offset for the ValueDecl from a + /// BlockDeclRefExpr in a block literal (BlockExpr). + uint64_t getBlockOffset(const BlockDeclRefExpr *E); + + /// BlockHasCopyDispose - True iff the block uses copy/dispose. + bool BlockHasCopyDispose; + + /// BlockDeclRefDecls - Decls from BlockDeclRefExprs in apperance order + /// in a block literal. Decls without names are used for padding. + llvm::SmallVector<const Expr *, 8> BlockDeclRefDecls; + + /// BlockDecls - Offsets for all Decls in BlockDeclRefExprs. + std::map<const Decl*, uint64_t> BlockDecls; ImplicitParamDecl *BlockStructDecl; ImplicitParamDecl *getBlockStructDecl() { return BlockStructDecl; } - llvm::Constant *GenerateCopyHelperFunction(const llvm::Type *); - llvm::Constant *GenerateDestroyHelperFunction(const llvm::Type *); + llvm::Constant *GenerateCopyHelperFunction(bool, const llvm::StructType *, + std::vector<HelperInfo> &); + llvm::Constant *GenerateDestroyHelperFunction(bool, const llvm::StructType *, + std::vector<HelperInfo> &); - llvm::Constant *BuildCopyHelper(const llvm::Type *); - llvm::Constant *BuildDestroyHelper(const llvm::Type *); + llvm::Constant *BuildCopyHelper(const llvm::StructType *, + std::vector<HelperInfo> &); + llvm::Constant *BuildDestroyHelper(const llvm::StructType *, + std::vector<HelperInfo> &); llvm::Constant *GeneratebyrefCopyHelperFunction(const llvm::Type *, int flag); llvm::Constant *GeneratebyrefDestroyHelperFunction(const llvm::Type *T, int); diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 70373031bb..9afe450c58 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -1326,8 +1326,7 @@ Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) { } Value *ScalarExprEmitter::VisitBlockExpr(const BlockExpr *BE) { - llvm::Value *V = CGF.BuildBlockLiteralTmp(BE); - return V; + return CGF.BuildBlockLiteralTmp(BE); } //===----------------------------------------------------------------------===// diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index adeb4ebfd4..a54f9bd235 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -32,7 +32,6 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) // FIXME: We need to rearrange the code for copy/dispose so we have this // sooner, so we can calculate offsets correctly. - BlockHasCopyDispose = false; if (!BlockHasCopyDispose) BlockOffset = CGM.getTargetData() .getTypeStoreSizeInBits(CGM.getGenericBlockLiteralType()) / 8; diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 2ac886d840..0b34d7a92d 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -266,7 +266,9 @@ public: //===--------------------------------------------------------------------===// llvm::Value *BuildBlockLiteralTmp(const BlockExpr *); - llvm::Constant *BuildDescriptorBlockDecl(uint64_t Size, const llvm::Type *); + llvm::Constant *BuildDescriptorBlockDecl(uint64_t Size, + const llvm::StructType *, + std::vector<HelperInfo> *); llvm::Function *GenerateBlockFunction(const BlockExpr *BExpr, const BlockInfo& Info, @@ -276,26 +278,6 @@ public: llvm::Value *LoadBlockStruct(); - /// BlockHasCopyDispose - True iff the block uses copy/dispose. - bool BlockHasCopyDispose; - - /// BlockDeclRefDecls - Decls from BlockDeclRefExprs in apperance order - /// in a block literal. Decls without names are used for padding. - llvm::SmallVector<const Expr *, 8> BlockDeclRefDecls; - - /// BlockOffset - The offset in bytes for the next allocation of an - /// imported block variable. - uint64_t BlockOffset; - /// BlockAlign - Maximal alignment needed for the Block expressed in bytes. - uint64_t BlockAlign; - - /// getBlockOffset - Allocate an offset for the ValueDecl from a - /// BlockDeclRefExpr in a block literal (BlockExpr). - uint64_t getBlockOffset(const BlockDeclRefExpr *E); - - /// BlockDecls - Offsets for all Decls in BlockDeclRefExprs. - std::map<const Decl*, uint64_t> BlockDecls; - llvm::Value *GetAddrOfBlockDecl(const BlockDeclRefExpr *E); const llvm::Type *BuildByRefType(QualType Ty, uint64_t Align); diff --git a/test/CodeGen/blocks-1.c b/test/CodeGen/blocks-1.c index b1f9d9bcdf..8b5de629e8 100644 --- a/test/CodeGen/blocks-1.c +++ b/test/CodeGen/blocks-1.c @@ -5,7 +5,7 @@ // RUN: grep "__Block_byref_id_object_copy_" %t | count 2 && // RUN: grep "__Block_byref_id_object_dispose_" %t | count 2 && // RUN: grep "i32 135)" %t | count 2 && -// RUN: grep "_Block_object_assign" %t | count 2 +// RUN: grep "_Block_object_assign" %t | count 6 #include <stdio.h> |