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
This commit is contained in:
Mike Stump 2009-03-05 01:23:13 +00:00
Родитель 7833ed2a6e
Коммит 797b632757
5 изменённых файлов: 55 добавлений и 29 удалений

Просмотреть файл

@ -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<const llvm::Type*> 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);
}

Просмотреть файл

@ -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

Просмотреть файл

@ -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<BlocksAttr>();
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)

Просмотреть файл

@ -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);

Просмотреть файл

@ -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 <stdio.h>
void test1() {