From: Mike Stump Date: Thu, 5 Mar 2009 01:23:13 +0000 (+0000) Subject: Add codegen support for __block variables to call _Block_object_dispose as necessary. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=797b6327571f9d7b1c45404a56ddcbf9b9298ae8;p=clang Add codegen support for __block variables to call _Block_object_dispose as necessary. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66117 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 00bda4689c..89b2b5ff13 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -34,8 +34,6 @@ Enable__block("f__block", llvm::Constant *CodeGenFunction::BuildDescriptorBlockDecl(uint64_t Size) { - const llvm::PointerType *PtrToInt8Ty - = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); const llvm::Type *UnsignedLongTy = CGM.getTypes().ConvertType(getContext().UnsignedLongTy); llvm::Constant *C; @@ -78,8 +76,6 @@ llvm::Constant *BlockModule::getNSConcreteGlobalBlock() { if (NSConcreteGlobalBlock) return NSConcreteGlobalBlock; - const llvm::PointerType *PtrToInt8Ty - = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); // FIXME: We should have a CodeGenModule::AddRuntimeVariable that does the // same thing as CreateRuntimeFunction if there's already a variable with the // same name. @@ -96,8 +92,6 @@ llvm::Constant *BlockModule::getNSConcreteStackBlock() { if (NSConcreteStackBlock) return NSConcreteStackBlock; - const llvm::PointerType *PtrToInt8Ty - = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); // FIXME: We should have a CodeGenModule::AddRuntimeVariable that does the // same thing as CreateRuntimeFunction if there's already a variable with the // same name. @@ -164,8 +158,6 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { // __isa C = CGM.getNSConcreteStackBlock(); - const llvm::PointerType *PtrToInt8Ty - = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty); Elts.push_back(C); @@ -335,9 +327,6 @@ const llvm::Type *BlockModule::getGenericBlockLiteralType() { if (GenericBlockLiteralType) return GenericBlockLiteralType; - const llvm::Type *Int8PtrTy = - llvm::PointerType::getUnqual(llvm::Type::Int8Ty); - const llvm::Type *BlockDescPtrTy = llvm::PointerType::getUnqual(getBlockDescriptorType()); @@ -351,10 +340,10 @@ const llvm::Type *BlockModule::getGenericBlockLiteralType() { // void (*__invoke)(void *); // struct __block_descriptor *__descriptor; // }; - GenericBlockLiteralType = llvm::StructType::get(Int8PtrTy, + GenericBlockLiteralType = llvm::StructType::get(PtrToInt8Ty, IntTy, IntTy, - Int8PtrTy, + PtrToInt8Ty, BlockDescPtrTy, NULL); @@ -368,9 +357,6 @@ const llvm::Type *BlockModule::getGenericExtendedBlockLiteralType() { if (GenericExtendedBlockLiteralType) return GenericExtendedBlockLiteralType; - const llvm::Type *Int8PtrTy = - llvm::PointerType::getUnqual(llvm::Type::Int8Ty); - const llvm::Type *BlockDescPtrTy = llvm::PointerType::getUnqual(getBlockDescriptorType()); @@ -386,13 +372,13 @@ const llvm::Type *BlockModule::getGenericExtendedBlockLiteralType() { // void *__copy_func_helper_decl; // void *__destroy_func_decl; // }; - GenericExtendedBlockLiteralType = llvm::StructType::get(Int8PtrTy, + GenericExtendedBlockLiteralType = llvm::StructType::get(PtrToInt8Ty, IntTy, IntTy, - Int8PtrTy, + PtrToInt8Ty, BlockDescPtrTy, - Int8PtrTy, - Int8PtrTy, + PtrToInt8Ty, + PtrToInt8Ty, NULL); getModule().addTypeName("struct.__block_literal_extended_generic", @@ -678,8 +664,6 @@ uint64_t CodeGenFunction::getBlockOffset(const BlockDeclRefExpr *BDRE) { } llvm::Value *BlockFunction::BuildCopyHelper(int flag) { - const llvm::PointerType *PtrToInt8Ty - = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); // FIXME: implement llvm::Value *V = llvm::ConstantInt::get(llvm::Type::Int32Ty, 43); V = Builder.CreateIntToPtr(V, PtrToInt8Ty, "tmp"); @@ -688,11 +672,33 @@ llvm::Value *BlockFunction::BuildCopyHelper(int flag) { } llvm::Value *BlockFunction::BuildDestroyHelper(int flag) { - const llvm::PointerType *PtrToInt8Ty - = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); // FIXME: implement llvm::Value *V = llvm::ConstantInt::get(llvm::Type::Int32Ty, 44); V = Builder.CreateIntToPtr(V, PtrToInt8Ty, "tmp"); V = Builder.CreateBitCast(V, PtrToInt8Ty, "tmp"); return V; } + +llvm::Value *BlockFunction::getBlockObjectDispose() { + if (CGM.BlockObjectDispose == 0) { + const llvm::FunctionType *FTy; + std::vector ArgTys; + const llvm::Type *ResultType = llvm::Type::VoidTy; + ArgTys.push_back(PtrToInt8Ty); + ArgTys.push_back(llvm::Type::Int32Ty); + FTy = llvm::FunctionType::get(ResultType, ArgTys, false); + CGM.BlockObjectDispose + = CGM.CreateRuntimeFunction(FTy, "_Block_object_dispose"); + } + return CGM.BlockObjectDispose; +} + +void BlockFunction::BuildBlockRelease(const VarDecl &D, llvm::Value *DeclPtr) { + llvm::Value *F = getBlockObjectDispose(); + llvm::Value *N, *V; + V = Builder.CreateStructGEP(DeclPtr, 1, "forwarding"); + V = Builder.CreateLoad(V, false); + V = Builder.CreateBitCast(V, PtrToInt8Ty); + N = llvm::ConstantInt::get(llvm::Type::Int32Ty, BLOCK_FIELD_IS_BYREF); + Builder.CreateCall2(F, V, N); +} diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h index bef745945f..3b9cc5053b 100644 --- a/lib/CodeGen/CGBlocks.h +++ b/lib/CodeGen/CGBlocks.h @@ -94,19 +94,26 @@ public: int GlobalUniqueCount; } Block; + llvm::Value *BlockObjectDispose; + const llvm::Type *PtrToInt8Ty; + BlockModule(ASTContext &C, llvm::Module &M, const llvm::TargetData &TD, CodeGenTypes &T, CodeGenModule &CodeGen) : Context(C), TheModule(M), TheTargetData(TD), Types(T), CGM(CodeGen), NSConcreteGlobalBlock(0), NSConcreteStackBlock(0), BlockDescriptorType(0), - GenericBlockLiteralType(0) { + GenericBlockLiteralType(0), BlockObjectDispose(0) { Block.GlobalUniqueCount = 0; + PtrToInt8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); } }; class BlockFunction : public BlockBase { + CodeGenModule &CGM; + public: - enum { + const llvm::Type *PtrToInt8Ty; + enum { BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)), block, ... */ BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */ @@ -140,7 +147,10 @@ public: CGBuilderTy &Builder; - BlockFunction(CGBuilderTy &B) : Builder(B) { } + BlockFunction(CodeGenModule &cgm, CGBuilderTy &B) + : CGM(cgm), Builder(B) { + PtrToInt8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); + } ImplicitParamDecl *BlockStructDecl; ImplicitParamDecl *getBlockStructDecl() { return BlockStructDecl; } @@ -148,6 +158,8 @@ public: llvm::Value *BuildCopyHelper(int flag); llvm::Value *BuildDestroyHelper(int flag); + llvm::Value *getBlockObjectDispose(); + void BuildBlockRelease(const VarDecl &D, llvm::Value *DeclPtr); }; } // end namespace CodeGen diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 9cdb40b121..a01aad66b0 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -227,6 +227,7 @@ const llvm::Type *CodeGenFunction::BuildByRefType(QualType Ty, void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { QualType Ty = D.getType(); bool isByRef = D.getAttr(); + bool needsDispose = false; llvm::Value *DeclPtr; if (Ty->isConstantSizeType()) { @@ -371,6 +372,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { Builder.CreateStore(BuildDestroyHelper(flag), destroy_helper); } + needsDispose = true; } // Handle the cleanup attribute @@ -388,6 +390,11 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { EmitCall(CGM.getTypes().getFunctionInfo(FD), F, Args); } + + if (needsDispose) { + CleanupScope scope(*this); + BuildBlockRelease(D, DeclPtr); + } } /// Emit an alloca (or GlobalValue depending on target) diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 0e9bf1a5bb..b8e01029f7 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -24,7 +24,7 @@ using namespace clang; using namespace CodeGen; CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) - : BlockFunction(Builder), CGM(cgm), Target(CGM.getContext().Target), + : BlockFunction(cgm, Builder), CGM(cgm), Target(CGM.getContext().Target), DebugInfo(0), SwitchInsn(0), CaseRangeBlock(0), InvokeDest(0) { LLVMIntTy = ConvertType(getContext().IntTy); LLVMPointerWidth = Target.getPointerWidth(0); diff --git a/test/CodeGen/blocks-1.c b/test/CodeGen/blocks-1.c index 725d71fbc9..c397185e88 100644 --- a/test/CodeGen/blocks-1.c +++ b/test/CodeGen/blocks-1.c @@ -1,4 +1,5 @@ -// RUN: clang %s -emit-llvm -o %t -fblocks -f__block +// RUN: clang %s -emit-llvm -o %t -fblocks -f__block && +// RUN: grep "_Block_object_dispose" %t | count 3 #include void test1() {